하위 트리에서 빈 디렉토리를 모두 제거하는 방법은 무엇입니까?


151

하위 트리에서 빈 디렉토리를 모두 제거하려면 어떻게해야합니까? 나는 같은 것을 사용했다.

find . -type d -exec rmdir {} 2>/dev/null \;

그러나 빈 디렉토리 만 포함 된 디렉토리를 제거하려면 여러 번 실행해야합니다. 또한 특히 cygwin에서는 속도가 느립니다.


emacs 솔루션에 대해서는 emacs.stackexchange.com/q/12190/2264 도 참조하십시오 .
Sean Allred

답변:


221

GNU find옵션과 술어를 결합 하여이 명령은 다음 작업을 수행해야합니다.

find . -type d -empty -delete
  • -type d 디렉토리로 제한
  • -empty 비어있는 것으로 제한
  • -delete 각 디렉토리를 제거합니다

나무는에 -depth의해 암시 된대로 명시 할 필요없이 나뭇잎에서 걸어 온다 -delete.


2
-delete이미 암시 -depth하므로 수동으로 지정할 필요가 없습니다.
jamadagni

1
고마워, 나는 그것을 몰랐다. 답변이 업데이트되었습니다.
Christophe Drevet-Droguet

11
-mindepth 1시작 디렉토리 자체가 비어 있으면 삭제하지 않도록 여기에 추가 합니다.
Greg Dubicki

2
훌륭하지만 내 오래된 SunOS 호스트에서는 작동하지 않습니다 ...
dokaspar

2
!쉘에 특별한 의미가 있습니다. 당신은 그것을 탈출해야합니다. \! -name 'Completed'바로 전에 : -delete작동해야합니다. 또는이 디렉토리에 마커 파일을 넣습니다.
Christophe Drevet-Droguet

53

가장 깊게 중첩 된 디렉토리를 나열하십시오.

find . -depth -type d -exec rmdir {} \; 2>/dev/null

(리디렉션 findrmdir. 뿐만 아니라 명령 전체에 적용됩니다 . 단지 리디렉션 rmdir을 수행하면 중간 쉘을 호출해야하므로 상당한 속도 저하가 발생합니다.)

발견 rmdir-empty술어를 전달하여 비어 있지 않은 디렉토리에서 실행 되는 것을 피할 수 있습니다 . GNU find는 명령을 실행하려고 할 때 디렉토리를 테스트하므로 방금 비운 디렉토리가 선택됩니다.

find . -depth -type d -empty -exec rmdir {} \;

속도를 높이는 또 다른 방법은 rmdir호출 을 그룹화하는 것 입니다. 둘 다 특히 Cygwin에서 원본보다 눈에 띄게 빠를 수 있습니다. 나는이 둘 사이에 큰 차이를 기대하지 않습니다.

find . -depth -type d -print0 | xargs -0 rmdir 2>/dev/null
find . -depth -type d -exec rmdir {} + 2>/dev/null

비어있는 디렉토리 수에 따라 더 빠른 방법이 있습니다. -empty호출을 그룹화하는 메소드와 결합 할 수 없습니다. 빈 디렉토리 만 포함하는 디렉토리는 볼 때까지 비어 있지 않기 때문 find입니다.

다른 방법은 여러 패스를 실행하는 것입니다. 이것이 더 빠른지 여부는 전체 디렉토리 계층이 find실행 사이의 디스크 캐시에 남아있을 수 있는지 여부를 포함하여 많은 것들에 달려 있습니다 .

while [ -n "$(find . -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done

또는 zsh를 사용하십시오. 글로브 규정이 F 때문에, 비어 있지 않은 디렉토리에 일치 /^F빈 디렉토리와 일치합니다. 빈 디렉토리 만 포함 된 디렉토리는 쉽게 일치시킬 수 없습니다.

while rmdir **/*(/N^F); do :; done

rmdir빈 명령 줄이 수신 되면 종료됩니다 .


그게 다야. 90 초 대신 0.90 초가 걸립니다.
maaartinus

@maaartinus : 궁금합니다. 비슷한 데이터 세트를 사용하지 않고 시도 할 수 -p있습니까? 나는 그것이 차이를 만들 것이라고 생각하지 않았을 것입니다.
Gilles

3
@maartinus-다른 작은 최적화 : 추가 -empty는 이것과 함께 작동해야합니다 (정확히 얼마나 많이 얻을지는 확실하지 않지만). 그리고 매우 사소하게, 당신은 아마 제거하고 싶지 않기 때문에를 .사용하십시오 -mindepth 1.
mattdm

그것은 제거가 아니라 프로세스 시작 오버 헤드, 거의 모든 시간이 걸렸습니다. 나는 그 -depth주장 을 간과 해 버렸기 때문에 rmdir -p쓸모 없게되었다. 내 의견을 이미 변경했습니다. 90 년대는 나의 최초의 시도였다. 여기서 놀라운 것은 없습니다.
maaartinus

2
rmdir최소한 다음 명령으로 GNU find를 사용 하여 명령 호출을 모두 제거 할 수 있다는 것을 깨달았습니다 .find . -depth -type d -empty -delete
Christophe Drevet-Droguet

6

당신은 단지 압정 경우 -p당신에 rmdir, 그 한 번에 작업 할 수 있습니다. 예쁘거나 최적은 아니지만 모든 것을 얻을 수 있습니다. 이것은 rmdir에게 제거중인 디렉토리의 비어 있지 않은 부모 디렉토리를 제거하도록 지시합니다.

-empty찾기 위해 테스트를 추가하여 조금만 저장할 수 있으므로 비어 있지 않은 디렉토리는 신경 쓰지 않습니다.


3

find . -depth -type d -exec rmdir {} +

이 질문에 대한 가장 단순하고 표준을 준수하는 답변입니다.

불행히도 여기에 제공된 다른 답변은 모든 시스템에 존재하지 않는 공급 업체별 개선 사항에 달려 있습니다.


3
이 답변은 삭제할 수없는 각 디렉토리에 대해 바람직하지 않은 오류를 발생시킵니다.
Willem van Ketwich

0

find . -type d -printf "%d %p\n" |\ sort -nr |\ perl -pe 's/^\d+\s//;' |\ while read dir; do \ (rmdir "$dir" > /dev/null 2>&1); \ done

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

  1. 깊이와 함께 모든 디렉토리를 재귀 적으로 나열
  2. 깊이의 내림차순으로 정렬
  3. 디렉토리 경로 만 필터링
  4. rmdir목록에서 하나씩 실행

0

자주 사용하는 find명령에 이러한 별칭을 사용 합니다. 특히 dupeguru를 사용하여 디스크 공간을 정리할 때 복제본을 제거하면 많은 빈 디렉토리가 생성 될 수 있습니다.

내부의 의견 .bashrc은 나중에 조정해야 할 때 나중에 잊지 않도록합니다.

# find empty directories
alias find-empty='find . -type d -empty'

# fine empty/zero sized files
alias find-zero='find . -type f -empty'

# delete all empty directories!
alias find-empty-delete='find-empty -delete'

# delete empty directories when `-delete` option is not available.
# output null character (instead of newline) as separator. used together
# with `xargs -0`, will handle filenames with spaces and special chars.
alias find-empty-delete2='find-empty -print0 | xargs -0 rmdir -p'

# alternative version using `-exec` with `+`, similar to xargs.
# {}: path of current file
# +: {} is replaced with as many pathnames as possible for each invocation.
alias find-empty-delete3='find-empty -exec rmdir -p {} +'

# for removing zero sized files, we can't de-dupe them automatically
# since they are technically all the same, so they are typically left
# beind. this removes them if needed.
alias  find-zero-delete='find-zero -delete'
alias find-zero-delete2='find-zero -print0 | xargs -0 rm'
alias find-zero-delete3='find-zero -exec rm {} +'

-2

rm -r */명령은 나를 위해 쉽게 일했다. 파일이있는 디렉토리를 강제로 제거 rm해야 -f합니다. rm -r빈 디렉토리 만 제거해야합니다. 나는 이것이 왜 틀릴 수 있는지에 대해 열려 있습니다. */폴더 만 보이 므로 파일도 남겨 두어야합니다 .


1
rm주로 파일을 제거하기 위해 철저히 테스트하는 것이 좋습니다 . */디렉토리와 만 일치 하지만 더 깊은 수준에서 수행되는 작업을 모릅니다. 또한 일부 시스템에서만 작동한다고 상상할 수 있습니다.
maaartinus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.