특정 파일 없이 폴더를 표시하는 방법을 알고 싶습니다. 그런데 문제는 파일명은 같지만 경우가 다르다는 것입니다.
사례 분석: tools 디렉터리의 일부 하위 디렉터리에는 readme
/ README
파일이 포함되어 있고 일부 하위 디렉터리에는 포함되어 있지 않습니다. 예를 들어
/toola/readme
/toolb/README
/toolc/ (does not have readme file)
이 명령을 사용하여 find 명령을 사용하여 toolc 폴더만 표시하고 싶습니다.
find . -maxdepth 2 ! -name '*readme*' -o ! -name '*README*' | awk -F "/" '{print $$2}' | uniq
그러나 이것은 작동하지 않습니다. toola
없음 README
및 toolb
없음 으로 모든 파일을 표시합니다.readme
답변1
find
존재하지 않는 파일을 찾는 데는 사용할 수 없습니다 . 그러나 이를 사용하여 find
디렉터리를 찾은 다음 해당 디렉터리에 지정된 파일 이름이 있는지 테스트할 수 있습니다.
find
디렉토리 찾기를 사용할 때 . 를 사용한 -type d
다음 찾은 각 디렉토리의 파일을 테스트하십시오 README
.readme
일부 최상위 디렉토리에 다음과 같은 디렉토리 계층 구조가 있다고 가정합니다 projects
.
projects/
|-- toola
| |-- doc
| |-- readme
| `-- src
|-- toolb
| |-- doc
| `-- src
|-- toolc
| |-- README
| |-- doc
| `-- src
`-- toold
|-- doc
`-- src
파일을 포함하지 않는 바로 아래 디렉토리를 찾는 데 사용됩니다 find
.projects
README
readme
$ find projects -mindepth 1 -maxdepth 1 -type d \
! -exec test -f {}/README ';' \
! -exec test -f {}/readme ';' -print
projects/toolb
projects/toold
여기에서 바로 아래 디렉터리를 찾은 projects
다음 test
유틸리티를 사용하여 발견된 디렉터리 중 이 두 파일 중 하나도 포함하지 않는 디렉터리를 확인합니다.
이는 정확히 다음과 같습니다.
find projects -mindepth 1 -maxdepth 1 -type d \
-exec [ ! -f {}/README ] ';' \
-exec [ ! -f {}/readme ] ';' -print
위의 또 다른 표현은 다음과 같습니다.
find projects -mindepth 1 -maxdepth 1 -type d -exec sh -c '
for pathname do
if [ ! -f "$pathname/README" ] &&
[ ! -f "$pathname/readme" ]; then
printf "%s\n" "$pathname"
fi
done' sh {} +
여기에는 실제로 이 두 파일을 테스트하고 둘 중 어느 것도 포함하지 않는 디렉토리의 경로 이름을 인쇄하는 작은 인라인 쉘 스크립트가 있습니다. 이 find
유틸리티는 인라인 스크립트가 반복할 수 있도록 디렉토리 경로 이름에 대한 "경로 이름 생성기" 역할을 합니다.
실제로 디렉토리 구조가 다음과 같다면 find
전혀 사용하지 않을 수도 있습니다.
for pathname in projects/*/; do
if [ ! -f "$pathname/README" ] &&
[ ! -f "$pathname/readme" ]; then
printf '%s\n' "$pathname"
fi
done
패턴의 후행 슬래시를 참고하세요 projects/*/
. 이는 패턴이 디렉토리(또는 디렉토리에 대한 심볼릭 링크)에만 일치하도록 하는 것입니다.
이를 수행하는 것과 사용하는 것의 차이점 find
은 위의 쉘 루프를 사용하면 아래의 숨겨진 디렉토리를 제외 project
하고 디렉토리에 대한 심볼릭 링크를 포함한다는 것입니다.
모든 경우에 우리는 디렉토리의 경로 이름을 반복하고 두 파일 이름이 모두 존재하지 않는지 테스트합니다.
유일하게 주목해야 할 점은 이 -f
테스트가 일반 파일에 대한 심볼릭 링크에도 작동한다는 것입니다.
관련된:
답변2
나는 명확성과 우아함에 투표하는 반면해결책저자: Kusalananda 나는 이런 종류의 작업이 세트에서 작업하는 것처럼 보인다고 덧붙였습니다. 단순한 도구는 find
적합하지 않습니다. 실제로는 사용을 통해 외부 도구를 가져와야 합니다 -exec
.
또 다른 방법은 비교/차이 도구를 사용하는 것입니다. 예를 들어, GNU find
및 프로세스 대체를 지원하는 셸(예: ) 에 액세스할 수 있고 bash
경로에 줄 바꿈이 없다고 가정합니다.
comm -2 -3 <(find ./tool* -maxdepth 0 -type d | sort) \
<(find ./tool* -iname "readme" -printf "%H\n" | sort)
어디:
comm
두 가지를 비교하다정렬됨행별 파일. 이 옵션을 사용-2
-3
하면 두 번째 파일의 결과만 제거하거나 출력에서 두 파일을 모두 제거할 수 있습니다.-printf "%H\n"
find
찾은 파일의 시작점과 새 줄을 인쇄해 보겠습니다 (-maxdepth 0
다른 목록을 정의하는 옵션과 일치해야 합니다).
트리로 테스트:
$ find ./tool* -printf "%p %y\n" | sort
./toola d
./toola/doc d
./toola/readme f
./toola/src d
./toolb d
./toolb/doc d
./toolb/src d
./toolc d
./toolc/doc d
./toolc/README f
./toolc/src d
./toold d
./toold/doc d
./toold/doc/readme f
./toold/src d
위 명령은 다음을 제공합니다.
./toolb
답변3
그리고 zsh
:
set -o extendedglob # for (#i) for case insensitive matching
all_projects=(projects/*(-/))
typeset -aU projects_with_readme # -U for unique
projects_with_readme=(projects/*/(#i)readme(:h))
projects_without_readme=(${all_projects:|projects_with_readme})
echo Projects with READMEs:
printf ' - %s\n' $projects_with_readme
echo Projects without READMEs:
printf ' - %s\n' $projects_without_readme
(#i)readme
다음 으로 변경하여 (#i)*readme*
명명된 README.txt
파일 만 고려 000README
하거나 다음으로 (:h)
변경할 수 있습니다.(-.:h)
읽어보기 파일파일은정기적인기호 링크 확인 후(디렉토리, 끊어진 링크 및 기타 특수 유형의 파일 제외)
답변4
나는 다음을 사용합니다 :
find -type d -maxdepth 2 -not -name '*readme*' | awk -F "/" '{print $$2}' | uniq