큰 타르가 있고 정기적으로 해당 내용을 고정된 위치에 추출한다고 가정해 보겠습니다.
나는 이 위치를 추출된 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 도구 또는 호환 및 sponge
from 을 가정합니다. 그렇지 않으면 파일을 삭제하면 상위 디렉터리의 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
여기 명령은 그렇지 않습니다.제거하다무엇이든 인쇄됩니다.아니요우리 아카이브에 포함되어 있습니다.