if
특정 패턴과 일치하는 파일이 있는지 테스트하기 위해 명령문 을 작성하려고합니다 . 디렉토리에 텍스트 파일이 있으면 주어진 스크립트를 실행해야합니다.
내 코드는 현재 :
if [ -f /*.txt ]; then ./script fi
몇 가지 아이디어를주십시오. .txt
디렉토리에 스크립트가있는 경우에만 스크립트를 실행하고 싶습니다 .
if
특정 패턴과 일치하는 파일이 있는지 테스트하기 위해 명령문 을 작성하려고합니다 . 디렉토리에 텍스트 파일이 있으면 주어진 스크립트를 실행해야합니다.
내 코드는 현재 :
if [ -f /*.txt ]; then ./script fi
몇 가지 아이디어를주십시오. .txt
디렉토리에 스크립트가있는 경우에만 스크립트를 실행하고 싶습니다 .
답변:
[ -f /*.txt ]
있을 경우에만 true를 돌려 것 하나 (단 하나)에서 숨겨지지 않은 파일 /
이름이 끝에서 .txt
해당 파일이 일반 파일이나 일반 파일에 대한 심볼릭 링크와 경우를.
와일드 카드는 명령 (여기 [
) 으로 전달되기 전에 쉘에 의해 확장되기 때문 입니다.
거기있어 경우에 따라서 /a.txt
하고 /b.txt
, [
(5 개) 인수를 전달합니다 : [
, -f
, /a.txt
, /b.txt
와 ]
. [
그런 다음 -f
너무 많은 주장이 주어 졌다고 불평합니다 .
*.txt
패턴이 숨겨지지 않은 하나 이상의 파일 (일반 또는 비 확장)로 확장되는지 확인하려면 다음을 수행하십시오 .
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "$@" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob
이다 bash
특정하지만, 쉘 좋아 ksh93
, zsh
, yash
, tcsh
해당 문장이있다.
참고는 디렉토리의 내용을 읽고 해당 파일을 발견 한, 그것은 시도하고 솔루션보다 더 효율적으로 만드는 전혀 그 파일에 액세스하지 않는 등의 호출 명령 ls
또는 stat
쉘에 의해 계산 된 파일의 목록.
sh
이에 상응 하는 표준은 다음 과 같습니다.
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "$@"
esac
문제는 Bourne 또는 POSIX 쉘에서 패턴이 일치하지 않으면 자체로 확장된다는 것입니다. 따라서로 *.txt
확장 하면 디렉토리에 파일 *.txt
이 없거나이라는 .txt
파일 이 있는지 여부를 알 수 없습니다 *.txt
. 를 사용 [*].txt *.txt
하면 둘을 구별 할 수 있습니다.
[ -f /*.txt ]
에 비해 상당히 빠릅니다 compgen
.
[ -f /*.txt ]
는 잘못되었지만 숨겨진 테스트 3425
파일 94
이 아닌 파일 을 포함하는 디렉토리의 테스트에서 (10000 회 반복하면 20.5 초) compgen -G "*.txt" > /dev/null 2>&1
빠릅니다 set -- *.txt; [ "$#" -gt 0 ]
.
당신은 항상 사용할 수 있습니다 find
:
find . -maxdepth 1 -type f -name "*.txt" 2>/dev/null | grep -q . && ./script
설명:
find
파일을 찾지 못하면 파일을 찾지 못하는 경우에만 false를 반환합니다. 결과물 grep -q .
이 있는지 확인 하기 위해 출력을 파이프하려고합니다 .
chmod a-x .
.
가능한 해결책은 Bash 내장 compgen
입니다. 이 명령은 글 로빙 패턴에 대해 가능한 모든 일치 항목을 리턴하며 파일이 일치하는지 여부를 나타내는 종료 코드를 갖습니다.
compgen -G "/*.text" > /dev/null && ./script
그래도 더 빠른 솔루션을 찾는 동안이 질문을 찾았습니다.
LC_ALL=C compgen -G "*.txt" > /dev/null
.
여기에 하나의 라이너가 있습니다.
$ ls
file1.pl file2.pl
$ stat -t *.pl >/dev/null 2>&1 && echo "file exists" || echo "file doesn't exist"
file exists
$ stat -t -- *.txt >/dev/null 2>&1 && echo "file exists" || echo "file don't exist"
file don't exist
이 접근 방식은 bash 에서 ||
and &&
연산자를 사용합니다 . 이들은 "또는"및 "및"연산자입니다.
따라서 stat 명령 $?
이 0과 같은 값을 반환 하면 첫 번째 echo
가 호출 되고 1 이 반환되면 두 번째 echo
가 호출됩니다.
# a failure
$ stat -t -- *.txt >/dev/null 2>&1
$ echo "$?"
1
# a success
$ stat -t -- *.pl >/dev/null 2>&1
$ echo "$?"
0
이 질문은 stackoverflow에서 광범위하게 다루어집니다.
stat
할 ls -d
수 있을 때 비표준을 사용 합니까?
ls -d
디렉토리가 있다고 생각 합니까? ls -d *.pl
예를 들어 파일이있는 디렉토리를 나열하려고했을 때 작동하지 않는 것 같습니다 .
&&
by 왼쪽의 문을 바꿀 수 있으며 ls *.txt
잘 작동합니다. /dev/null
@slm에서 제안한대로 stdout 및 stderr을 보내십시오 .
ls *.txt
하고 디렉토리에 파일이 없으면 이것은을 반환하며 $? = 2
, 여전히 if와 함께 작동하지만 이것이 선택 stat
을 위한 나의 이유 중 하나였습니다 ls
. 나는 성공을 위해 0을, 실패를 위해 1을 원했다.
ls -d
내용 대신 디렉토리를 나열하는 것입니다. 그래서 ls -d
단지를 수행 lstat
GNU이처럼 파일에 stat
않습니다. 실패시 0이 아닌 종료 상태 명령이 리턴하는 것은 시스템마다 다르며, 명령을 가정하는 것은 의미가 없습니다.
Chazelas가 지적했듯이 와일드 카드 확장이 둘 이상의 파일과 일치하면 스크립트가 실패합니다.
그러나, 내가 사용하는 트릭이 있습니다 ( 심지어별로 싫어합니다 ).
PATTERN=(/*.txt)
if [ -f ${PATTERN[0]} ]; then
...
fi
어떻게 작동합니까?
와일드 카드 확장은 파일 이름 배열과 일치합니다. 파일 이름이 있으면 첫 번째 파일 이름을 얻습니다. 일치하지 않으면 null입니다.
.txt
유형의 다른 파일이 있을 수도 있습니다 . 예를 들어 이후에보십시오 . mkdir a.txt; mkfifo b.txt; echo regular > c.txt
다음과 같이 간단합니다.
cnt=`ls \*.txt 2>/dev/null | wc -l`
if [ "$cnt" != "0" ]; then ./script fi
wc -l
확장 된 와일드 카드의 행을 계산합니다.
ls
이미 $?
직접 수행하므로 직접 검사하지 마십시오 if
. 또한 어떤 일 이 일어 났는지 확인하기 위해 사용 wc
하는 것도 마찬가지로 잘못 지시됩니다.
이전 배열 솔루션이 마음에 들지만 많은 파일로 인해 낭비 될 수 있습니다. 쉘은 많은 메모리를 사용하여 배열을 빌드하며 첫 번째 요소 만 테스트합니다.
어제 테스트 한 대체 구조는 다음과 같습니다.
$ cd /etc; if [[ $(echo * | grep passwd) ]];then echo yes;else echo no;fi
yes
$ cd /etc; if [[ $(echo * | grep password) ]];then echo yes;else echo no;fi
no
grep의 종료 값이 제어 구조를 통한 경로를 결정하는 것으로 보입니다. 또한 쉘 패턴이 아닌 정규식으로 테스트합니다. 내 시스템 중 일부에는 "pcregrep"명령이있어 훨씬 더 복잡한 정규식 일치를 허용합니다.
(이 구문 분석에 대한 위의 비판을 읽은 후 명령 대체에서 "ls"를 제거하기 위해이 답변을 편집했습니다.)
/
합니까? 또한 전에 세미콜론이 누락되었습니다fi
.