어리석은 점은 스크립트에서 다음과 같은 조건문을 계속 사용한다는 것입니다.
if [ $(ls FOO* 2> /dev/null) ] # if files named "FOO*" were downloaded
then
echo "Files found"
# ... process and email results
else
echo "Not found"
# ... email warning that no files were found (against expectations)
fi
이는 다음에 적용됩니다.0과 1의 파일명명 FOO*
하지만둘 이상이면 실패. 로그에서 여러 가지 다른 오류 메시지를 발견했습니다.
[: FOO_20131107_082920: unary operator expected
[: FOO_20131108_070203: binary operator expected
[: too many arguments
내 질문은: Bash 조건부에서 if
올바른지 확인하는 방법은 무엇입니까?하나 이상해당 이름으로 시작하는 파일이 FOO
존재합니까?
GNU bash, 버전 4.2.25(1)-릴리스(x86_64-pc-linux-gnu)
답변1
이는 ls에 대한 명령이 출력을 공백으로 바꾸고 에 전달되기 전에 토큰화를 거치기 때문에 발생합니다 [
. 깨지지 않는 방법은 파일을 배열에 넣은 다음 배열에 멤버가 하나 이상 있는지 확인하는 것입니다.
shopt -s nullglob
files=( FOO* )
if (( ${#files[@]} )); then
# there were files
fi
((
이는 기본적으로 값이 0이 아닌 경우 true를 반환하고 ${#files[@]}
배열의 항목 수(glob과 일치하는 파일이 있는 경우 >0이 됨)를 가져오기 때문에 작동합니다 .
설정되지 않은 한 다음 nullglob
과 같은 작업을 수행할 수도 있습니다.
if ls FOO* >/dev/null 2>&1; then
# there were files
fi
ls
이는 존재하지 않는 파일 이름을 전달하는 경우(문자 그대로 FOO*
, 일치하는 파일 이름이 없으면 해당 종료 코드가 1이 되는 종료 코드를 확인합니다 . 물론 사용자가 사악하고 이름이 파일 FOO*
이름인 경우 는 제외) 0을 반환합니다 :-) )).
이 두 개는 디렉터리와도 일치합니다. 정말로 일반 파일만 일치시키려면 다음을 테스트해야 합니다.
for file in FOO*; do
if [[ -f $file ]]; then
# file found, do some stuff and break
break
fi
done
답변2
위의 여러 줄 답변은 환경을 수정하지 않는 한 줄 솔루션에 대한 나의 욕구를 충족시키지 못합니다. 다음은 귀하에게 도움이 될 수 있는 일반적인 한 줄의 내용입니다.
echo $(ls FOO* 2>/dev/null | wc -w)
/dev/null은 ls
파일이 없으면 오류가 발생하기 때문입니다. 이것은 단지 ls를 무시하고 "단어"(실제로는 파일 이름) 수를 기준으로 찾은 파일 수를 계산합니다. 간단한 if 문에서 사용할 수 있습니다.
if [ 0 -lt $(ls FOO* 2>/dev/null | wc -w) ]; then
echo "Some FOO is there."
fi
이 접근 방식은 일치하는 파일이 있는지 확인할 수 있을 뿐만 아니라 유연성을 제공합니다.얼마나일치하는 파일이 존재하고( 0
및/또는 변경만 하면 됨 -lt
) 거기서부터 계속 진행합니다.
와일드카드나 공백이 있는 파일/폴더를 확인하지 않았습니다. 위의 방법으로 인해 공백 수가 잘못 계산될 것으로 생각됩니다. 특히 0보다 큰 정확한 수가 필요한 경우 이는 문제일 뿐입니다. 이에 대해 제가 시도한 한 가지 수정 사항은 을 사용하는 것입니다. 이 방법은 $(ls -l FOO* 2>/dev/null | wc -l)
목록을 행별로 나누어 공백을 허용하는 것이 더 쉬워야 합니다.
답변3
또 다른 옵션이 있습니다.사례,
FILES=FOO*
FILES=$(echo $FILES)
case $FILES in FOO\*) echo "Not found" ;; esac
그 이유는 케이스가 하나의 매개변수만 테스트하면 되기 때문입니다.