세 가지 파일 형식이 모두 디렉터리에 있는지 테스트합니다.

세 가지 파일 형식이 모두 디렉터리에 있는지 테스트합니다.

.png.txt다음 파일 형식 중 하나가 디렉터리에 존재하는지 여부를 감지하고 싶습니다 .tar.gz.

다음 중 두 가지를 테스트할 때 제대로 작동했습니다.

shopt -s nullglob
MYDIR=/some_dir
if [ $MYDIR/*.png] && [ $MYDIR/*.txt]; then
  echo "All files present"
else
  echo "At least one type is missing"
fi

하지만 다음을 사용하여 세 가지를 모두 테스트하려고 하면

if [ $MYDIR/*.png] && [ $MYDIR/*.txt] && [ $MYDIR/*.tar.gz]; then
...

또는 사용

if [[ $MYDIR/*.png && $MYDIR/*.txt && $MYDIR/*.tar.gz ]]; then
...

글쎄요, 올바른 동작이 발생하지 않습니다(파일 중 하나가 누락된 경우에도 여전히 true를 반환합니다).

여기서 무슨 일이 일어나고 있는 걸까요?

답변1

파일 이름 와일드카드 패턴이 일치하는지 테스트할 수 없습니다(그리고 [ ... ]모든 테스트에서 마지막 공백 앞에 공백이 누락되어 코드가 작동하지 않습니다).][ ... ]

방법은 일치를 수행하고 일치하는 이름의 수를 계산하는 것입니다.

shopt -s nullglob    # make globs expand to nothing if they don't match
shopt -s dotglob     # also match hidden names

error=false
for ext in png txt tar.gz; do
    set -- "$MYDIR"/*."$ext"
    if [ "$#" -eq 0 ]; then
        printf 'Nothing matches "%s"\n' "$MYDIR/*.$ext" >&2
        error=true
        break  # possibly, unless you want the user to see all patterns that fail
    fi
done

if "$error"; then
    echo 'Can not continue' >&2
    exit 1
fi

더 많은 것을 입력하고 싶거나 기존 위치 인수 목록을 유지하고 싶다면 명명된 배열을 사용할 수 있습니다. set --행을 names=( "$MYDIR"/*."$ext" )"$#"로 변경합니다 "${#names[@]}". 모든 따옴표가 중요합니다.

답변2

반드시 다음을 사용해야 합니다.

shopt -s nullglob

말 그대로 테스트하기 전에 거짓 긍정을 피하십시오 $MYDIR/*.png.

하지만 Bash 테스트에서는 이와 같은 와일드카드를 테스트할 수 없으며 배열을 테스트해야 합니다.

txt=( *.txt ) tgz=( *.tar.gz ) png=( *.png )
if [[ ${txt[@]} && ${png[@]} && ${tgz[@]} ]]; then
    echo SUCCESS
fi

해킹을 사용하여 와일드카드가 있는지 테스트하는 또 다른 방법은 다음과 같습니다 compgen.

cd "$workdir"
if (compgen -W *.txt && compgen -W *.png && compgen -W *.tar.gz) &>/dev/null; then
    echo 'SUCCESS'
else
    echo >&2 'At least one filetype missed'
fi

bash shebang을 추가하는 것을 잊지 마세요:

#!/bin/bash

또는

#!/usr/bin/env bash

[[[명령 과 유사하지만 더 강력한 bash 키워드입니다 . 바라보다http://mywiki.wooledge.org/BashFAQ/031그리고http://mywiki.wooledge.org/BashGuide/TestsAndConditionals. POSIX sh에 글을 쓰는 것이 아니라면 추천합니다.[[

사용 예:

 [[ ${names[@]} ]] && echo 'SUCCESS'

당신이 하려고 하는 것처럼 발생 횟수를 셀 필요가 없습니다.

관련 정보