보존하려는 경로가 포함된 텍스트 파일이 있는 경우 예를 들면 다음과 같습니다.
/mnt/cache/vfs/cf/A/file
/mnt/cache/vfs/cf/B/file2
/mnt/cache/vfs/cf
내 텍스트 파일에 없는 내용을 제외하고 아래의 모든 내용을 지우고 싶습니다.
그래서 /mnt/cache/vfs/cf/Z/file3
삭제됐다 등등.
텍스트 파일이 크고 파일 이름에 공백과 가능한 악센트 또는 기타 특수 문자가 포함되어 있습니다.
답변1
파일 시스템의 파일을 나열하고, 보관하려는 파일 집합에 있는 파일을 삭제한 다음 나머지를 삭제합니다.
xargs
여기서는 공백이 포함된 파일 이름과 공백으로 구분된 부분 사이에 혼동이 없도록 항상 NULL로 끝나는 파일 이름을 사용합니다 .
find /mnt/cache/vfs/cf -type f -print0 |
LC_ALL=C sort -z |
LC_ALL=C comm -z -23 - <(LC_ALL=C sort list-of-files-to-keep.list | tr '\n' '\0') |
xargs -0 printf '%s\n' {}
삭제를 수행할 준비가 되면 로 바꾸십시오 printf '%s\n'
.rm --
이 comm
명령은 두 개의 정렬된 파일을 가져와 한 줄씩 비교합니다. 출력의 첫 번째 열은 첫 번째 파일의 항목만이고, 두 번째 열은 두 번째 파일의 항목만이며, 세 번째 열은 두 파일의 항목입니다. -1
, -2
및 한정자는 -3
해당 열의 출력을 억제하므로 comm -23
첫 번째 파일( -
, 즉표준 입력).
나는 로캘이 C
서로 일관된 방식으로 작동하도록 강제했고( sort
입력 정렬 필요) 각 줄을 결정적인 방식으로 정렬했습니다(일부 로캘은 문자 집합을 같은 방식으로 정렬하므로 이와 같은 문자 집합은 다음과 같이 정렬될 수 있습니다). 일관성 없는 방식).comm
comm
답변2
다음과 같이 간단한 단일 라이너를 사용합니다.
for FILE in $(ls /mnt/cache/vfs/cf); do grep "$FILE" keep_files.txt || rm "/mnt/cache/vfs/cf/$FILE"; done
하지만 삭제하려는 파일 수에 따라 필요한 파일을 실수로 삭제하지 않도록 항상 임시 디렉터리로 이동하는 것이 좋습니다. :)
답변3
나는 무엇을 할 것인가:
shopt -s extglob
cd /mnt/cache/vfs/cf
{ printf 'rm !('; awk -F'/mnt/cache/vfs/cf' '{print $2}' file |
paste -sd '|'
} | sed 's/$/)/'
출력이 만족스러우면 전체 코드 조각을 가져올 수 있습니다 bash
.
shopt -s extglob
cd /mnt/cache/vfs/cf
{ printf 'rm !('
awk -F'/mnt/cache/vfs/cf' '{print $2}' file |
paste -sd '|'
} | sed 's/$/)/' |
bash
바라보다http://mywiki.wooledge.org/glob#extglob
그리고https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html