스크립트를 실행하기 위해 패턴과 일치하는 파일이 있는지 테스트하십시오.

스크립트를 실행하기 위해 패턴과 일치하는 파일이 있는지 테스트하십시오.

if특정 패턴과 일치하는 파일이 있는지 테스트하는 명령문을 작성하려고 합니다 . 디렉터리에 텍스트 파일이 있으면 지정된 스크립트를 실행해야 합니다.

내 현재 코드:

if [ -f /*.txt ]; then ./script fi

.txt몇 가지 아이디어를 주십시오. 디렉토리에 있는 경우 에만 스크립트를 실행하고 싶습니다 .

답변1

[ -f /*.txt ]

존재하는 경우에만 true를 반환합니다.하나/(그리고 단 하나의) 이름이 로 끝나고 .txt일반 파일이거나 일반 파일에 대한 심볼릭 링크인 숨김되지 않은 파일 입니다.

[이는 와일드카드가 명령(여기 ) 에 전달되기 전에 쉘에 의해 확장되기 때문입니다 .

/a.txt따라서 and 가 있으면 /b.txt, , and 5 개의 [매개변수가 전달됩니다. 그러면 너무 많은 매개변수가 주어졌다고 불평할 것입니다.[-f/a.txt/b.txt][-f

*.txt패턴이 하나 이상의 숨겨지지 않은 파일(일반 또는 비정규)로 확장되는지 확인하려면 bash셸에서 다음을 수행합니다.

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( shopt예, nullglob실제로는 에서 유래 zsh), , , 와 같은 쉘에는 ksh93동일한 zsh명령문 yashtcsh있습니다.

그리고 zsh, 테스트는패턴과 일치하는 파일이 있나요?이는 익명 함수와 N(for nullglob) 및 Y1(첫 번째 조회 후 중지) glob 한정자를 사용하여 작성할 수 있습니다.

if ()(($#)) *.txt(NY1); then
  do-something
fi

이러한 파일은 디렉터리의 내용을 읽어 이러한 파일을 찾으며 파일에 전혀 액세스하려고 시도하지 않으므로 쉘 계산 파일 목록 ls과 같은 명령을 호출하는 것보다 더 효율적인 솔루션이 됩니다.stat

표준에 sh해당하는 것은 다음과 같습니다.

set -- [*].txt *.txt
case "$1$2" in
  ('[*].txt*.txt') ;;
  (*) shift; script "$@"
esac

문제는 Bourne 또는 POSIX 쉘의 경우 패턴이 일치하지 않으면 자체적으로 확장된다는 것입니다. 그래서 *.txt으로 확장 하면 디렉토리에 파일이 없어서 *.txt인지 .txt, 아니면 *.txt. 사용하면 [*].txt *.txt둘을 구별할 수 있습니다.

*.txt이제 적어도 하나와 일치하는지 확인하려면정기적인파일 또는 일반 파일에 대한 심볼릭 링크(제안한 대로 [ -f *.txt ]) 또는 일치하는 모든 파일 *.txt정기적인파일(심볼릭 링크 해결 후)은 또 다른 이야기입니다.

그리고 zsh:

if ()(($#)) *.txt(NY1-.); then
  echo "there is at least one regular .txt file"
fi
if ()(($#)) *.txt(NY1^-.); then
  echo "there is at least one non-regular .txt files"
fi

( -심볼릭 링크가 해결되기 전에 테스트하려면 제거하십시오. 즉, 심볼릭 링크가 일반 파일을 가리키는지 여부에 관계없이 비정규 파일로 처리하십시오.)

답변2

가능한 해결책은 Bash 내장 입니다 compgen. 이 명령은 일치하는 파일이 있는지 여부를 나타내는 종료 코드와 함께 와일드카드 패턴과 일치하는 모든 항목을 반환합니다.

compgen -G "/*.text" > /dev/null && ./script

더 빠른 솔루션을 찾는 동안 이 질문을 발견했습니다.

답변3

언제든지 다음을 사용할 수 있습니다 find.

find . -maxdepth 1 -type f -name "*.txt" 2>/dev/null | grep -q . && ./script

설명하다:

  • find .: 현재 디렉토리 검색
  • -maxdepth 1: 하위 디렉터리를 검색하지 않습니다.
  • -type f: 일반 파일만 검색
  • name "*.txt": 다음으로 끝나는 파일 검색.txt
  • 2>/dev/null: 오류 메시지를 다음으로 리디렉션합니다./dev/null
  • | grep -q .: 임의의 문자를 grep하고, 문자가 없으면 false를 반환합니다.
  • && ./script: ./script이전 명령이 성공한 경우에만 실행됩니다(&&)

답변4

Chazelas가 지적했듯이 와일드카드 확장이 두 개 이상의 파일과 일치하면 스크립트가 실패합니다.

그러나 나는 트릭을 사용했습니다 (내가 별로 좋아하지 않더라도) 우회:

PATTERN=(/*.txt)
if [ -f ${PATTERN[0]} ]; then
...
fi

어떻게 작동하나요?

와일드카드 확장은 파일 이름 배열과 일치하며 파일 이름이 있으면 첫 번째 파일 이름을 가져오고 일치 항목이 없으면 null을 가져옵니다.

관련 정보