다음과 같은 문제가 있습니다. 디렉터리 구조가 있고 디렉터리의 모든 항목을 삭제하고 싶습니다 Caches
. 이름이 지정된 모든 디렉터리를 제외하고 모든 내용을 삭제해야 합니다 Snapshots
. 나는 이것을하는 방법을 모른다찾다아니면 내가 아는 다른 명령이라도요.
제가 묻는 이유는 iOS에서 각 애플리케이션에 자체 Caches 디렉터리가 있기 때문입니다. 응용 프로그램에 따라 제대로 지워지지 않는 경우도 있습니다. 이 답변의 솔루션을 사용하면 FUSE(iExplorer)를 사용하는 등 장치의 드라이브가 다른 컴퓨터에 마운트될 때 iOS에서 캐시를 지워 디스크 공간을 최적화할 수 있습니다.
이것이 내가 지금까지 가지고 있는 것입니다:
find . 2>/dev/null -type d -name "Caches" -maxdepth 3 -print
그러면 다음과 유사한 내용이 반환됩니다.
./Library/Caches
내가 할 때 ls ./Library/Caches
나는 모든 콘텐츠와 Snapshots
디렉토리를 보고 궁극적으로 그것 이외의 모든 것을 원하기 때문에 그것들을 제외하고 싶습니다 -delete
.
나는 다음과 같은 것을 원합니다 :
Before: After:
. .
├── a ├── a
│ ├── a │ ├── a
│ └── Caches │ └── Caches
│ ├── a │ └── a
│ │ └── Snapshots │ └── Snapshots
│ │ └── a │ └── a
│ ├── b └── b
│ │ └── a └── c
│ └── c
└── b
├── c
└── Caches
├── a
│ └── foo
│ └── a
└── b
└── a
답변1
질문의 표현이 조금 혼란스럽네요. ./Library/Caches
이름이 지정된 단일 폴더를 제외하고 디렉토리의 모든 항목을 삭제하려는 경우 쉘 glob을 Snapshots
사용할 필요가 없는 가장 쉬운 방법은 다음과 같습니다.find
bash
shopt -s extglob # probably already enabled
echo Library/Caches/!(Snapshots)
삭제하려는 모든 파일/디렉토리가 인쇄되면 echo
로 바꾸십시오 rm -f --
.
Snapshots
디렉토리 트리의 서로 다른 수준에 여러 디렉토리를 유지하려면 GNU를 사용하여 다음을 수행할 수 있습니다../Library/Caches
find
find Library/Caches ! -path '*Snapshots*'
Snapshots
그러면 경로에 있는 파일/디렉터리를 제외한 모든 파일/디렉터리가 인쇄됩니다 . 여기에는 디렉터리(또는 포함된 하위 디렉터리)가 포함된 디렉터리 Snapshots
가 포함되지만 find ... -delete
해당 디렉터리는 삭제되지 않지만 비어 있지 않다는 오류가 인쇄됩니다. 만족스러우면 -delete
끝에 추가하세요.
이렇게 하면 모든 항목이 남게 됩니다.문서이름이 잘 지정되었습니다 Snapshots
. 이것이 문제인 경우 다음으로 변경하십시오.
find Library/Caches \( ! -path '*Snapshots*' -o -type f -name Snapshots \)
당신이 행복할 때 더 추가하십시오 -delete
.
답변2
find . -depth -print0 | perl -0lne '
if ("$_/" =~ m{/Caches(/.*)}s && $1 !~ m{/Snapshots/}) {rmdir $_ or unlink $_}'
find
지원하지 않는 경우 -print0
로 대체할 수 있습니다 -exec printf '%s\0' {} +
.
아이디어는 NUL로 끝나는 파일 목록을 인쇄하고(0은 파일 경로에 나타날 수 없는 유일한 바이트이므로) 옵션 ( filename 으로 perl
설정 )을 사용하여 각 파일 이름에 대해 일부 코드를 실행하는 것입니다.-n
-0
$_
를 사용하면 -depth
파일이 상위 디렉터리 앞에 인쇄됩니다. 파일이나 디렉터리 depth
의 경로 /Caches/
에 /Snapshosts/
.
답변3
저는 마법사가 아니기 find
때문에 이 작업을 수행하는 데 사용할 수 없다고 말하고 싶지는 않지만 find
몇 줄만 있으면 완료할 수 있다는 것을 알고 있습니다 bash
. 귀하의 디렉토리 구조를 올바르게 이해하고 있다고 가정하면 다음과 같습니다.
#!/bin/bash
for i in Library/Caches/*; do
if [[ -d "$i" ]]; then
[[ "$i" =~ "Snapshots" ]] || echo "rm-ing $i" # change to rm -rf "$i" to use
fi
done
이 for
문은 의 각 항목을 반환합니다 Library/Caches/
. 이 if [[ -d "$i" ]]
명령문은 각 항목이 디렉토리인지 확인하고, 그렇다면 이름에 "Snapshots" 가 포함되어 있는지 확인합니다 [[ "$i" =~ "Snapshots" ]]
. 정규식 일치를 무효화하는 연산자가 없기 때문에 !=~
이전 명령이 성공하지 못했을 때 (예: 디렉터리 이름에 스냅샷이 포함되지 않았을 때) ||
이를 수행 했습니다.rm
이것은 사용되는 모든 최신 시스템에서 작동 bash
하지만 반드시 작동해야 합니다 bash
. 또한 디렉토리 구조를 가지고 놀아야 할 수도 있지만 이것이 효과가 있을 것입니다.
답변4
1부: 캐시라는 이름의 디렉터리를 찾아 몇 가지 작업 수행
find . -name Caches -type d -exec … \;
2부: 캐시 디렉터리를 반복하고 모든 항목을 삭제하지만 Snapshots
하위 디렉터리와 해당 콘텐츠(및 해당 경로)는 유지합니다. 디렉터리가 비면 삭제할 수 있도록 깊이 우선 순회를 수행합니다.
find /path/to/Caches -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete
이제 그것들을 하나로 합치십시오.
find . -name Caches -type d -exec
find {} -depth -name Snapshots -type d -prune \
-o \( -type d -empty -o ! -type d \) -delete