주어진 파일 이름을 가진 파일을 포함하지 않는 모든 디렉토리 나열

주어진 파일 이름을 가진 파일을 포함하지 않는 모든 디렉토리 나열

모든 디렉토리를 어떻게 나열합니까?아니요주어진 파일 이름을 가진 파일이 있습니까? 예를 들어, 이 트리가 주어지면

/
  /a
     README
     file001
     file002
  /b
     README
     file001
  /c
     file003

이 작업을 수행하는 디렉토리를 나열하고 싶습니다.아니요라는 파일이 있는데 README, 이 경우에는 디렉토리가 됩니다 /c. 어떻게 해야 하나요? find예를 들어 구문을 생각할 수 없습니다 .

답변1

findGNU와 같은 구현이 매개변수 삽입을 find허용한다고 가정하면 다음과 같습니다 .{}-exec

$ find . -type d \! -exec test -e '{}/README' \; -print

또는 문제의 삽입 없이:

$ find . -type d ! -exec sh -c 'test -e "$1"/README' sh {} \; -print

여기서 1/1~5/5 디렉토리에는 README가 있고 나머지 디렉토리는 비어있습니다.

$ tree 
.
|-- 1
|   `-- 1
|       `-- README
|-- 10
|   `-- 10
|-- 2
|   `-- 2
|       `-- README
|-- 3
|   `-- 3
|       `-- README
|-- 4
|   `-- 4
|       `-- README
|-- 5
|   `-- 5
|       `-- README
|-- 6
|   `-- 6
|-- 7
|   `-- 7
|-- 8
|   `-- 8
`-- 9
    `-- 9

find이제 이 버전의 명령을 실행하면 다음과 같습니다 .

$ find . -type d \! -exec test -e '{}/README' \; -print
.
./10
./10/10
./7
./7/7
./9
./9/9
./6
./6/6
./5
./8
./8/8
./4
./1
./3
./2

인용하다

답변2

불필요한 find. 그냥 쉘을 사용하세요:

for d in */; do [ -f "$d"README ] || printf '%s\n' "$d"; done
c/

재귀가 필요한 경우 다음을 사용할 수 있습니다( 의 경우 bash기본적 zsh으로 이 작업을 수행할 수 있으며 set -o globstar에서 사용 ksh93).

shopt -s globstar
for d in **/; do [ -f "$d"README ] || printf '%s\n' "$d"; done

(닷 파일은 기본적으로 제외됩니다.)

답변3

-exec이 옵션을 사용하여 find파일을 확인한 다음 실패한 확인에 대한 결과를 인쇄할 수 있습니다 .

find /path/to/base -mindepth 1 -maxdepth 1 -type d -exec test -e {}/README \; -o -print

답변4

이식 가능한 방법은 다음과 같습니다.

find . -type d -exec sh -c '
  for dir do
    [ -f "$dir/README" ] || printf "%s\n" "$dir"
  done' sh '{}' +

[ -f file ]파일인지 테스트존재하다 그리고일반 파일로 확인되었습니다(심볼릭 링크 확인 후).

유형에 관계없이 해당 디렉토리의 항목으로만 존재하는지 테스트하려면 다음이 필요합니다. [ -e file ] || [ -L file ]그러나 이러한 테스트를 수행하려면 디렉토리에 대한 검색 권한이 필요합니다. [ -x "$dir" ]이러한 상황을 설명하기 위해 몇 가지 테스트를 추가해야 할 수도 있습니다 . 예를 들면 다음과 같습니다.

find . -type d -exec sh -c '
  for dir do
    if [ -x "$dir" ]; then
      [ -f "$dir/README" ] || printf "%s\n" "$dir"
    else
      printf >&2 "Cannot tell for \"%s\"\n" "$dir"
    fi
  done' sh '{}' +

또는 경쟁 조건을 피하려면 다음을 사용하십시오 zsh.

find . -type d -exec zsh -c '
  zmodload zsh/system
  for dir do
    ERRNO=0
    if [ ! -f "$dir/README" ]; then
      if [ "$errnos[ERRNO]" = ENOENT ]; then
        printf "%s\n" "$dir"
      else
        syserror -p "ERROR: $dir/README: "
      fi
    fi
  done' zsh '{}' +

당신은 또한 볼 수 있습니다Bash에 일반 파일이 없는지 어떻게 알 수 있습니까?그게 다야.

관련 정보