tar의 압축을 디렉토리에 풀고 아카이브에 없는 모든 파일을 제거합니다.

tar의 압축을 디렉토리에 풀고 아카이브에 없는 모든 파일을 제거합니다.

큰 타르가 있고 정기적으로 해당 내용을 고정된 위치에 추출한다고 가정해 보겠습니다.

나는 이 위치를 추출된 tar의 원래 인스턴스로 유지하고 싶고 tar에 있을 수 있는 작은 변경 사항을 업데이트하기 위해 항상 출력 디렉터리를 지우는 매우 낭비적인 프로세스를 피할 수 있습니다 --keep-newer-files.

하지만 아카이브에 더 이상 존재하지 않는 파일을 출력 위치에서 어떻게 삭제합니까?

답변1

표준 tar명령에는 아카이브 내용을 나열하는 방법이 있습니다. 그 약어는 입니다 tar -tf archive.tar.

find, 및 명령 대체 와 함께 사용하면 grep다음과 같은 결과를 얻을 수 있습니다.

rm -f $(find . -d | head -n -1 | grep -Fv "$(tar -tf archive.tar)")

이것을 실행존재하다콘텐츠를 보관하려는 디렉터리로, archive.tar보관 파일의 경로로 대체됩니다.

가장 바깥쪽 명령 대체 내부에 있는 파이프의 경우 오른쪽에서 왼쪽으로 작업합니다.

  • find . -d: 현재 디렉터리의 모든 파일과 디렉터리를 깊이 우선 순서로 나열합니다. 여기서는 이 파일 목록을 삭제에 사용할 계획이므로 깊이 우선 정렬이 중요하므로 디렉터리 자체를 삭제하기 전에 디렉터리 내용을 삭제해야 합니다.
  • head -n -1:명령에서 마지막 줄을 제외합니다 find. 그러면 /path아카이브에 존재하거나 존재하지 않을 수 있는 항목 자체가 삭제됩니다 . 깊이 우선 순서로 작업을 수행하지 않으면 이는 가 됩니다 tail -n -1.
  • grep -Fv "$(tar -tf archive.tar)": 아카이브 목록을 grep 명령에 전달하면 반환된 목록에서 해당 줄이 필터링되므로 find아카이브에 없는 파일만 외부 rm명령에 전달됩니다.

몇 가지 참고사항:

  • 이건 아닐 수도 있어상당히POSIX 표준을 준수합니다. 하지만 GNU bash에서는 작동합니다.
  • 이는 tar가 아카이브의 내용을 보고하는 방법과 아카이브가 생성된 방법에 따라 다릅니다. 특히 목록은 find보고 방법과 일치해야 합니다. GNU tar 및 대부분의 아카이브의 경우~해야 한다일하다. 귀하의 경우에 작동하지 않는 경우 가장 안쪽 명령 치환 내에서 또는 tar 명령의 출력을 사용하여 sed작동하게 할 수 있습니다.awk
  • 프로덕션 데이터에 사용하기 전에 확인하고 테스트하세요. 위에서 언급한 두 가지 이유 중 하나로 인해 작동하지 않으면 제거될 수 있습니다.모든 것실행할 디렉터리를 만듭니다.

답변2

ctime추출된 파일이 아카이브 추출을 시작한 시간 보다 이후라는 것을 신뢰할 수 있습니다 .

그래서:

touch start
tar xf archive.tgz
find . -depth ! -cnewer start -print0 |
  sponge /dev/stdout |
  xargs -r0 echo rm -d

(이는 전체 목록이 수집될 때까지 삭제를 지연하는 데 사용되는 GNU 도구 또는 호환 및 spongefrom 을 가정합니다. 그렇지 않으면 파일을 삭제하면 상위 디렉터리의 ctime이 업데이트됩니다.)moreutils

실제로 이 작업을 수행하려면 제거하십시오 echo(원하는 작업을 수행하는지 확인한 후).

답변3

grep -v아카이브가 약간 크고 명령이 통과되었기 때문에 이 트릭은 나에게 작동하지 않았습니다.매개변수 목록이 너무 깁니다.. MediaWiki 설치에 쌓인 정크를 제거하기 위해 제가 사용하는 방법은 다음과 같습니다:

$ tar -tzf mediawiki-1.35.0.tar.gz | cut -d/ -f2- > foo
$ find /var/www/mediawiki/ | cut -d/ -f5- | while read f;
     do grep -qw "^${f}$" foo || echo "not in archive: ${f}"; done

-f올바른 결과를 얻으려면 매개변수를 약간 조정해야 하는데 cut여기 명령은 그렇지 않습니다.제거하다무엇이든 인쇄됩니다.아니요우리 아카이브에 포함되어 있습니다.

관련 정보