특정 패턴과 일치하지 않는 파일이 디렉터리에 있는지 테스트합니다.

특정 패턴과 일치하지 않는 파일이 디렉터리에 있는지 테스트합니다.

나는 이것 때문에 많은 어려움을 겪고 있습니다. 디렉터리에 특정 패턴과 일치하지 않는 파일이 있는지 테스트하려고 하며 true 또는 false를 반환합니다.

이 경우 $dir파일이 밑줄로 시작하지 않는 경우 시도해 볼 것이라고 _생각했습니다.if [ -f $dir/!(_*) ]if [ $dir -f -name ! _* ]

또는 if ls $dir/!(_*) 1> /dev/null 2>&1

하지만 항상 말 Too many arguments 하거나syntax error near unexpected token "("

답변1

names=( "$dir"/[!_]* )

if [ -e "${names[0]}" ]; then
    echo 'there are filenames that do not start with underscore'
    printf '%d of them\n' "${#names[@]}"
fi

또는 그 문제에 대해 /bin/sh( bash그 문제에 대해):

set -- "$dir"/[!_]*

if [ -e "$1" ]; then
    echo 'there are filenames that do not start with underscore'
    printf '%d of them\n' "$#"
fi

즉, 적절한 와일드카드 패턴을 확장하고 그것이 존재하는 것과 일치하는지 테스트하십시오.

[!_]패턴은 밑줄이 아닌 모든 문자와 일치합니다. 그것은 비슷하다정규식 [^_], 그러나 부정 문자 클래스 !대신 파일 이름 글로빙 패턴이 사용됩니다 .^

언제 모드아니요일치하면 기본적으로 확장되지 않은 상태로 유지되므로 테스트를 사용하여 -e일치 목록의 첫 번째 항목이 있는지 확인합니다. 반환된 목록의 길이를 실제로 테스트할 수는 없습니다. 길이가 1인 경우에도 여전히 어떤 것과도 일치하지 않을 수 있기 때문입니다( nullglob에서 쉘 옵션을 설정하지 않는 한 bash).

테스트하고 싶다면 조금 까다로워집니다.일반 파일특히 와일드카드 패턴이 일치하기 때문에어느이름(디렉터리, 일반 파일 및 기타 모든 유형의 파일) 하지만 이렇게 하면 다음과 같은 작업이 수행됩니다.

names=( "$dir"/[!_]* )

while [ "${#names[@]}" -gt 0 ] && [ ! -f "${names[0]}" ]; do
    names=( "${names[@]:1}" )
done

if [ -f "${names[0]}" ]; then
    echo 'there are at least one regular file here (or a symlink to one)'
    echo 'whose filename does not start with underscore'
fi

또는 다음의 경우 /bin/sh:

set -- "$dir"/[!_]*

while [ "$#" -gt 0 ] && [ ! -f "$1" ]; do
    shift
done

if [ -f "$1" ]; then
    echo 'there are at least one regular file here (or a symlink to one)'
    echo 'whose filename does not start with underscore'
fi

이 방법은 또한 감지할 ​​수 있습니다심볼릭 링크이름이 밑줄로 시작하지 않는 일반 파일로.

비정규 파일과 일치시킬 수 있는 파일 이름(예: 디렉터리 이름)을 제거하려면 루프가 필요합니다.

셸에서는 zsh일치하는 항목이 있는 경우 일반 파일만 일치하도록 보장되는 패턴을 사용할 수 있습니다."$dir"/[^_]*(.)


더 복잡한 패턴의 경우 일치하는 항목 수를 일치하는 항목 수와 순진하게 비교할 수 있습니다 *. 다르다면 복잡한 패턴과 맞지 않는 이름이 있는 것입니다.

에서는 bash쉘 활성화 옵션을 사용한 후 확장 글로빙 모드를 사용할 수 있습니다. 일반적인 형태는 위와 같이 확장 결과를 확인하여 어떤 것으로든 확장되는지 확인해야 합니다.!(PATTERN)extglobshopt -s extglob!(pattern1|pattern2|pattern3|etc)

밑줄로 시작하지 않는 이름의 예는 !(_*)확장된 globbing 패턴을 사용할 수 있지만 이는 !(_)*보이는 모든 이름과 일치하므로 작동하지 않는다는 점에 유의하세요 *.

관련 정보