목록과 일치하지 않는 폴더 삭제

목록과 일치하지 않는 폴더 삭제

Linux에서 목록에 없는 폴더를 삭제하는 방법에 대한 실제적인 예가 필요합니다. 따라서 내용이나 md5sum을 비교할 필요가 없으며 폴더 이름만 비교할 필요가 있습니다.

예를 들어 한 폴더에 여러 개의 폴더가 있습니다.

target_folder/
├── folder1
├── folder2
├── folder3
└── folder4

내 폴더 이름 목록은 폴더1, 폴더2를 포함하고 폴더3 및 폴더4를 제외한 txt 파일입니다.

bash 스크립트를 통해 폴더3 및 폴더4를 삭제하는 방법은 무엇입니까?

이것은 serverfault에서 답변되었습니다.

GLOBIGNORE=folder1:folder2
rm -r *
uset GLOBIGNORE

하지만 내 실제 임무는 여러 폴더를 삭제하는 것입니다. txt 목록에는 약 100개의 폴더가 포함되어 있으며 정리할 대상 폴더는 200개의 폴더입니다.

이는 Linux와 FreeBSD 모두에서 작동합니다.

편집하다: target_folder에는 파일뿐만 아니라 하위 폴더가 있는 폴더도 포함될 수 있습니다. 공백 및 선행 점 및 유사하지 않은 이름: foo.com bar.orgemptydir file.txt simplefile. 하지만 목록에 있는 이름을 제외한 모든 항목을 제거해야 합니다.

첫 번째 대답은 더 명확하고 간단합니다. 두 번째는 더욱 발전되고 유연하며, 항목 유형에 따라 삭제할 수도 있습니다.

답변1

파일 이름에 가 포함되어 있지 않다고 가정하면 을 :\[*?계속 사용할 수 있습니다 GLOBIGNORE. 그에 따라 디렉터리 목록의 형식을 지정하면 됩니다. 예를 들어:

$ cat names.txt
folder1
folder3

이는 콜론으로 구분된 목록으로 쉽게 변환됩니다.

$ paste -s -d : names.txt
folder1:folder3

따라서 이제 GLOBIGNORE 값으로 설정할 수 있습니다.

GLOBIGNORE=$(paste -s -d : ../names.txt)

정상적으로 삭제를 진행합니다.

rm -r -- *

방금 300개의 디렉토리가 있는 Linux에서 테스트했는데 제대로 작동했습니다.

답변2

이건 어때?

find ./target_folder/ \
    -mindepth 1 \
    -maxdepth 1 \
    -type d \
    -not -name 'anything[0-9]*' \
    -exec rm -rf {} \;

설명하겠습니다.

  • -mindepth 1일치하지 않는지 확인하세요../target_folder/
  • -maxdepth 1일치하는 하위 폴더가 없는지 확인하세요.
  • -type d파일이 아닌 디렉터리만 일치하도록 find에 지시합니다.
  • -not -name 'anything[0-9]*'패턴과 일치하는 패턴에서 모든 항목을 제외합니다. 분명히, 그거요.
  • -exec특히 사용할 때는 주의하세요 rm. 당신은해야언제나echo이 방법으로 진행하기 전에 테스트해 보십시오 rm -rf. find까다로울 수 있다
  • \;exec를 사용할 때 후행을 잊지 마세요.

find자세한 내용은 매뉴얼 페이지를 읽어보세요 . 이것은매우 편리함도구.

답변3

간단한 방법은 모든 파일을 나열하고 목록 파일의 파일을 무시하는 것입니다. 간단한 방법으로 포함 여부를 확인할 ignore_list수 있도록 변수를 개행 문자로 시작하고 끝나도록 배열했습니다. 포함 여부 를 확인하는 것만으로는 무시 목록과 같은 이름의 요소도 일치하므로 포함 여부를 확인하는 것은 작동하지 않습니다.$x$ignore_list$x

newline='
'
ignore_list="$newline$(cat list.txt)$newline"
cd target_folder
for x in * .[!.]* ..?*; do
  case "$x" in *"$newline"*) continue;; esac   # sanity check: if the file name contains a newline, leave it alone
  case "$ignore_list" in
    *"$newline$x$newline"*) echo "Skipping $x";;
    *) rm -rf -- "$x";
  esac
done

답변4

배쉬에서 이것을 할 수 있습니다

for folder in /target_folder/*/
do
    folder=${folder%/}
    if ! grep -qx "${folder##*/}" folders_list.txt
    then
        rm -rf "$folder"
    fi
done

관련 정보