나는 여러 개의 디렉토리를 가지고 있는데 그 중 일부는 3개 깊이이고 혼합된 파일 유형을 포함하고 있습니다. 내가 해야 할 일은 rm -rf
filetype 을 포함하지 않는 모든 하위 디렉터리 입니다 foo
.
이것이 find
어떻게든 달성될 수 있습니까? 나는 다음과 같이 find를 사용할 수 있다는 것을 알고 있습니다.
find . ! -name '*.foo' -delete
어떤 유형의 파일도 포함하지 않은 디렉터리의 모든 파일을 삭제합니다 *.foo
. 이제 이것을 사용하여 불필요한 파일뿐만 아니라 포함되지 않은 모든 디렉터리와 하위 디렉터리도 삭제하려면 어떻게 해야 합니까 *.foo
?
답변1
(귀하의 질문은 불분명합니다. 디렉토리에 some.foo
및 가 포함되어 있으면 some.bar
삭제해야 합니까? 저는 이것을 그러한 디렉토리를 보존해야 한다는 의미로 해석했습니다.)
파일 이름에 개행 문자가 포함되어 있지 않고 디렉터리가 일치하지 않는 경우 *.foo
다음 스크립트가 작동합니다 . 원칙은 디렉토리가 잎에서 위쪽으로( ) -depth
탐색되고 , *.foo
파일이 발견되면 포함 디렉토리와 모든 상위 디렉토리가 표시된다는 것입니다 protected
. 도착한 보호되지 않은 파일은 *.foo
삭제될 디렉터리입니다. 순회 순서 로 인해 -depth
디렉토리는 항상 *.foo
보호할 수 있는 파일 다음에 도달합니다. 경고: 최소한의 테스트만 수행하면 제거에 따른 책임은 echo
본인에게 있습니다.
find . -depth -name '*.foo' -o -type d | awk '{
if ($0 ~ /\.foo$/) {
while (sub("/+[^/]+$", "")) {protect[$0]=1;}
} else {
if (!protect[$0]) {
gsub("[\\\001-/]", "\\\\&"); # protect file names for xargs
print;
}
}
}' | xargs echo rm -rf
이번에는 zsh 솔루션을 제안하지 않겠습니다.
답변2
이것이 just를 사용하여 수행될 수 있는지 확실하지 않지만, find
just 및 를 사용하여 수행할 수 있다고 생각합니다.bash
find
tree_contains_foo_files()
{
# return true (0) as soon as we find a "*.foo" file
find "$1" -type f -name "*.foo" -print0 |
read -r -d $'\0' file && return 0
return 1
}
find . -depth -type d -print0 |
while read -r -d $'\0' dir; do
if ! tree_contains_foo_files "$dir"; then
rm -rf "$dir"
fi
done
이 테스트 트리가 주어지면:
.
./dir1
./dir1/dir1.1
./dir1/dir1.1/dir1.1.1
./dir1/dir1.1/dir1.1.1/file.foo
./dir1/dir1.1/file.bar
./dir2
./dir2/dir2.1
./dir2/file.bar
./dir3
나는 다음과 같은 결과를 얻습니다.
rm -rf ./dir2/dir2.1
rm -rf ./dir2
rm -rf ./dir3
나는 이것이 당신이 원하는 것이라고 생각합니다. 즉, include dir1
때문에 삭제하지 마십시오 .dir1/dir1.1/dir1.1.1
file.foo
그러나 디렉터리를 여러 번 처리하므로 큰 트리의 경우 속도가 느려질 수 있습니다. 효율성이 중요하다면 더 강력한 프로그래밍 언어를 사용하겠습니다.
답변3
IIUYC, 먼저 다음 명령을 사용하여 불필요한 파일을 모두 삭제할 수 있습니다
find . ! -type f -name '*.foo' -delete
이로 인해 일부 디렉터리가 지워질 수 있습니다. 그런 다음 빈 디렉터리(및 빈 디렉터리만 포함하는 디렉터리 등)를 삭제할 수 있습니다.내 질문
find . -depth -mindepth 1 -empty -type d -exec rmdir -p -- {} +
답변4
허용 되지 않는 경우 find
더 간단한 해결책은 다음과 같습니다.
find -type d -not -path . | while IFS='' read -r path; do [[ ! -e "$path/$notThisFile" ]] && echo "$path"; done
-e
원하는 테스트로 교체하세요 .
를 포함하지 않는 모든 내용이 인쇄되어야 합니다 $notThisFile
.
파일이 포함된 숨겨지지 않은 모든 하위 디렉터리가 강조 표시되는 자세한 예:
find -type d -not -path . | while IFS='' read -r path; do
[[ ! -e "$path/$notThisFile" ]] && echo "$path"
done | sed -r 's~^([^.]*)/'"$notThisFile"'$~\033[1;37m\1\033[0m~''