다음과 같은 파일 시스템 구조를 가정합니다.
ROOT
DIR1A
FILE
DIR2A
DIR2B
DIR3A
DIR1B
DIR2C
DIR2D
DIR3B
DIR1C
DIR2E
FILE
임의의 디렉터리에서 시작하여, 빈 하위 디렉터리를 나열하지 않고 a) 아무것도 포함하지 않거나 b) 빈 디렉터리만 포함하는 가장 얕은 하위 디렉터리만 나열하려면 어떻게 해야 합니까?
즉, 위의 경우 ROOT에서 시작하면 다음과 같습니다.
- DIR1A에는 파일이 포함되어 있으므로 나열되지 않습니다.
- DIR2A에는 아무것도 포함되어 있지 않으므로 나열됩니다.
- DIR2B에는 빈 디렉터리만 포함되어 있으므로 나열됩니다.
- DIR3A는 이미 나열된 더 얕은 디렉터리에 있으므로 나열되지 않습니다.
- DIR1B에는 빈 디렉터리만 포함되어 있으므로 나열됩니다.
- DIR1B의 하위 디렉터리는 이미 나열된 더 얕은 디렉터리에 있으므로 나열되지 않습니다.
- DIR1C나 DIR2E에는 파일이 중첩되어 있으므로 나열되지 않습니다.
나는 이것을 표현하는 더 효율적인 방법이 있다고 믿습니다. 어쩌면 "아무것도 포함하지 않거나 빈 디렉토리만 포함하는 최상위 디렉토리만 나열하고 싶습니다."?
편집: 위의 언어 중 일부를 명확히 하려고 했습니다.
답변1
디렉터리 트리를 너무 많이 탐색하지 않고 실행되는 명령 수를 최소화하려면 다음을 수행할 수 있습니다(GNU find
및 sort
유사한 NUL을 ecord 구분 기호 awk
로 지원한다고 가정 ).R
S
find . -type d -print0 -o -printf 'f/%h\0' |
LC_ALL=C sort -zru |
LC_ALL=C awk -F/ -vRS='\0' '
function parent(path) {
sub("/[^/]*$", "", path)
return path
}
$1 == "f" {
sep = path = ""
for (i = 2; i <= NF; i++) {
black[path = path sep $i]
sep = FS
}
next
}
! ($0 in black) && ($0 == "." || parent($0) in black)'
그 아래에 디렉토리가 아닌 파일이 있는 모든 디렉토리를 검은색으로 색칠한 다음 검은색 부모가 있는(또는 특수한 경우 부모가 없는 .
) 검정색이 아닌 디렉토리를 인쇄합니다.
이러한 디렉터리를 삭제하는 것이 목표라면 다음과 같이 할 수 있습니다.
find . -depth -type d -empty -delete
-delete
을 의미 -depth
하지만 명확성을 위해 여기에 추가하겠습니다(GNU find
매뉴얼에서 제안한 대로). -delete
어떤 경우든 빈 디렉터리만 삭제되므로 -empty
비어 있지 않은 디렉터리를 삭제할 수 없을 때 발생하는 오류 메시지를 방지할 수 있습니다. 깊이 우선을 사용 d
하면 디렉토리가 아닌 파일을 제외한 전체 구조를 삭제하고 리프가 있는 분기 이전의 리프를 삭제하게 됩니다 .
-delete
BSD 및 GNU의 비표준 확장이지만 -empty
둘 다 현재 상당히 일반적입니다. 해당 항목이 없으면 언제든지 두 개를 다음으로 대체할 수 있습니다(아마도 오류 메시지를 다음으로 삭제할 수 있음).-delete
-empty
find
find
-exec rmdir {} +
2> /dev/null
모두find
및) 오류 메시지 rmdir
.
답변2
뒤늦게 이렇습니다.
find -type d -exec sh -c '[ -z "$(find "$@" -type f -print -quit)" ]' _ {} \; -print -prune
예
# Setup your configuration
mkdir -p root/{dir1a/{dir2a,dir2b/dir3b},dir1b/{dir2c,dir2d/dir3b},dir1c/dir2e}
touch root/{dir1a,dir1c/dir2e}/file
# Run the finder
find root -type d -exec sh -c '[ -z "$(find "$@" -type f -print -quit)" ]' _ {} \; -print -prune
# Output
root/dir1b
root/dir1a/dir2b
root/dir1a/dir2a
설명하다
하위 쉘은 각 디렉토리에 대해 차례로 호출되며 exec
, 맨 위에서 시작하여 아래쪽으로(즉, 너비 우선) 작업됩니다. 현재 위치부터 파일을 검색하여 파일 true
이 없으면 반환합니다. main은 find
그것으로부터 상태 결과를 얻고 exec
성공하면 현재 디렉토리를 인쇄하고 나머지 하위 트리 검색을 중지합니다.