하나의 파일이 포함되어 있지만 다른 파일이 누락된 디렉터리 검색

하나의 파일이 포함되어 있지만 다른 파일이 누락된 디렉터리 검색

나는 현재 다음과 같이 디렉토리를 검색하고 특정 파일을 포함하지 않는 디렉토리를 나열하는 방법을 알고 있습니다.

find parent_directory -mindepth 1 -maxdepth 1 -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^file_name$"' \; -print

하지만 이제 결과 디렉토리를 사용하여 다른 파일이 포함되어 있는지 확인하고 싶지만 확장된 단일 행 표현식에서는 이를 수행할 수 없습니다. 이것이 가능한가?

답변1

다음을 통해 필요한 디렉터리를 결정할 수도 있습니다.

find . -maxdepth 2 -path '*/*/wanted.txt' -type f \
  -execdir test ! -f unwanted.txt \; -execdir pwd \;

작동 방식은 다음과 같습니다.

  • 깊이가 2인 항목을 찾습니다.
  • 2개의 슬래시가 있으므로 이 -path옵션은 깊이를 2로 제한합니다. 최대 깊이는 추가 진행을 방지하고 2개의 명시적 슬래시는 깊이가 2 미만을 방지하기 때문입니다.
  • 깊이 수준 2에서 발견된 Wanted.txt 항목은 일반 파일인 것이 바람직하며 다음을 통해 보장됩니다.-type f
  • -execdir옵션은 Wanted.txt가 있는 디렉터리로 작업을 승격시켜 test명령이 원하지 않는 파일을 찾습니다.
  • -execdir다음으로, 원치 않는 파일이 발견되지 않은(승격된 대로) 디렉토리를 인쇄하는 간단한 문제입니다.
  • 이에 대해 자세히 설명하지 않고 디렉토리는 특정 파일을 한 번만 포함할 수 있으므로 -execdir작업은 /directory에서 한 번 실행되고 최소한 일반 파일 Wanted.txt를 포함하는 것이 확실한 디렉토리에서만 실행됩니다.

답변2

하위 디렉터리로 재귀적으로 이동하고 싶지 않은 것 같으므로 특정 파일이 없는 디렉터리를 찾는 데 필요한 것은 다음과 같습니다.

for dir in */; do [ ! -e "$dir"/"$filename" ] || printf '%s\n' "$dir"; done

그리고 그 중 실제로 다른 파일이 있는 파일을 확인하려면 다음을 수행하세요.

for dir in */; do 
    [ ! -e "$dir"/"$filename1" ] && 
    [ -e "$dir"/"$filename2" ] && 
    printf '%s\n' "$dir"; 
done

또는 약간 더 명확한 구문을 사용하면 다음과 같습니다.

for dir in */; do 
    if [ ! -e "$dir"/"$filename1" ]; then 
        if [ -e "$dir"/"$filename2" ]; then 
            printf '%s\n' "$dir"; 
        fi 
    fi
 done

이 모든 작업은 셸에 내장된 도구를 사용하여 수행됩니다. 구체적으로:

  • [: 이것과 그에 수반되는 것들은 ]내장 함수의 동의어입니다 test( sh 스타일 쉘을 사용하는 경우 help [또는 참조). help test이는 셸에서 테스트 작업을 작성하는 방법입니다.
  • -e: 파일/디렉토리 등이 존재하는지 테스트합니다. 바라보다 help test. 간단한 형식은 [ -e file ]존재하는 경우 true를 반환하는 것입니다.file
  • [ ! -e filename ]: !테스트를 거꾸로 하면 됩니다. 그렇다면 그것은 [ ! -e file ]사실이다file아니요존재하다.

전체적으로 이는 위 명령이 다음을 수행함을 의미합니다.

## Iterate over every directory (dirs only because of the '/' in '*/')
## saving each of them in the variable $dir.
for dir in */; do 
    ## If this $dir does not contain $filename1
    if [ ! -e "$dir"/"$filename1" ]; then 
        ## If this $dir does contain $filename2
        if [ -e "$dir"/"$filename2" ]; then 
            ## Print the directory name
            printf '%s\n' "$dir"; 
        fi 
    fi
done

물론, 실행하려면 먼저 $filename1적절하게 설정 해야 합니다 $filename2. 예를 들어:

filename1="unwantedFile"
filename2="wantedFile"

답변3

파일 이외의 zsh파일이 포함된 현재 디렉토리의 디렉토리를 나열하려면 , 를 사용하십시오 .musthavemustnothave

contain() [[ -e $REPLY/$1 || -L $REPLY/$1 ]]

printf '%s\n' *(D/e(contain musthave)^e(contain mustnothave))

다음을 수행하십시오.

find ... -exec sh -c 'ls {}' \;

이식성이 없을 뿐만 아니라 명령 주입 취약점이기도 합니다. 예를 들어, $(reboot)또는이라는 디렉터리가 있으면 ;reboot또는 명령줄 ls $(reboot)ls ;reboot실행되어 재부팅됩니다. {}코드 매개변수(또는 다른 언어)에 포함되어서는 안 됩니다. sh그렇지 않으면 오해될 수 있습니다. 사용:

find ... -exec sh -c 'ls "$1"' sh {} \;

대신에.

관련 정보