파이프라인에서 다른 tar 파일을 생성하기 위해 tar 파일의 내용을 필터링하는 방법은 무엇입니까?

파이프라인에서 다른 tar 파일을 생성하기 위해 tar 파일의 내용을 필터링하는 방법은 무엇입니까?

권한, mtimes 등과 같이 보존하고 싶은 다양한 속성이 있는 일부 디렉터리가 포함된 외부 시스템의 단일 tar 파일을 생각해 보세요. 일반 사용자(루트 대신)로서 이러한 파일의 하위 집합을 쉽게 얻을 수 있는 방법은 무엇입니까?

비슷한 것을 찾고 있습니다.

tar -f some.tar.gz --subset subdir/ | ssh remote@system tar xvz

이 tar 아카이브에서 주요 속성(소유권, 그룹, 모드, mtime)을 보존하는 것도 중요합니다. tar 파일의 다른 속성(예:제목 키워드 확장?

해당 하위 디렉터리에 대용량 파일이 포함되어 있는 경우 임시 디렉터리 사용을 피하는 솔루션에 대한 보너스 포인트입니다.

답변1

bsdtar(libarchive 기반)표준 입력에서 표준 출력으로 tar(및 기타 일부 아카이브)를 필터링할 수 있습니다. 예를 들어,일치하는 파일 이름만 전달패턴이며 s/old/new/이름을 바꿀 수 있습니다. Ubuntu와 같은 대부분의 배포판에는 이미 패키지되어 있습니다.bsdtar libarchive-tools

sudo apt-get install libarchive-tools   # or aptitude, if you have it.

# example from the man page:
bsdtar -c -f new.tar --include='*foo*' @old.tgz
#create new.tar containing only entries from old.tgz containing the string ‘foo’
bsdtar -czf - --include='*foo*' @-  # filter stdin to stdout, with gzip compression of output.

입력/출력을 위해 선택할 수 있는 압축 형식이 여러 가지 있으므로 gunzip/lz4를 통해 수동으로 파이프할 필요가 없습니다. -stdin 을 사용 @tarfile하거나 -평소대로 stdout 을 사용하는 구문을 사용할 수 있습니다 .


내 검색에서도 이 스트리밍 tar 수정 도구가 나타났는데, 이는 자바스크립트를 사용하여 필요한 아카이브 변경 사항을 정의하기를 원하는 것으로 보입니다. (모든 것이 js로 작성된 것 같습니다.)

https://github.com/mafintosh/tar-stream

답변2

가장 쉬운 방법은 전체 아카이브를 복사하는 것입니다. 너무 크기 때문에 그렇게 하고 싶지 않을 것입니다.

일반적인 명령줄 도구( tar, pax)는 한 아카이브의 멤버를 다른 아카이브로 복사하는 것을 지원하지 않습니다.

소유권을 유지할 필요가 없다면 다음을 사용하는 것이 좋습니다.퓨즈파일 시스템. 당신은 그것을 사용할 수 있습니다아카이브 마운트아카이브를 파일 시스템으로 마운트합니다. 소스 아카이브에서 이 작업을 수행하고 마운트된 파일 시스템에서 tar를 실행합니다.

archivemount some.tar.gz mnt
cd mnt
tar -cz subdir | ssh example.com tar -xz
fusermount -u mnt

또는 다음을 사용할 수 있습니다.AVFS:

mountavfs
cd ~/.avfs$PWD/some.tar.gz\#
tar -cz subdir | ssh example.com tar -xz

또는 tar원본 아카이브에서 실행하고 다음을 통해 원격 시스템으로 추출할 수 있습니다.SSHFS.

sshfs example.com: mnt
cd mnt
tar -xf /path/to/some.tar.gz subdir
fusermount -u mnt

그러나 소유권을 유지해야 하는 경우 이러한 모든 방법은 번거롭습니다. 모두 로컬 컴퓨터의 파일로 추출하는 작업이 포함되므로 파일의 소유권은 예상대로여야 합니다.외딴소유권. 이 작업은 루트로 실행해야 하며 로컬 시스템과 원격 호스트 간에 이름이나 ID가 다른 계정이 파일을 소유한 경우 예상한 결과를 제공하지 못할 수 있습니다.

파이썬tarfile라이브러리는 tar 멤버를 조작하여 하나의 tar 파일에서 다른 tar 파일로 이동할 수 있는 매우 간단한 방법을 제공합니다. POSIX 표준 형식(ustar, pax)과 일부 GNU 확장을 지원합니다. 이것은 표준 입력(gzip 또는 bzip2 압축 사용 가능)에서 tar 파일을 읽고 표준 출력에 bzip2 압축 tar 파일을 쓰는 테스트되지 않은 Python 스크립트입니다. 소스의 멤버가 스크립트에 전달된 매개변수로 시작하는 경우 해당 멤버가 복사됩니다.

#!/usr/bin/env python2
import sys, tarfile
source = tarfile.open(fileobj=sys.stdin)
destination = tarfile.open(fileobj=sys.stdout, mode='w:bz2')
for info in source:
    if info.name.startswith(sys.argv[1]):
        destination.addfile(info)
destination.close()

다음과 같이 불린다.

tar_filter <some.tar.gz subdir/ | ssh example.com tar -xj

답변3

GNU에는 다음과 같은 옵션이 tar있습니다 --delete.

$ tar -c a b c | tar --delete a | tar -t
b
c

이 방법으로 무엇을 지정하여 입력 tar의 하위 집합을 얻을 수 있습니다.아니요출력에 포함됩니다.

--exclude불행하게도 사용된 옵션을 얻을 수 없으므로 먼저 제거할 항목에 대한 명시적인 목록()을 --delete얻은 다음 이를 다른 호출에 전달해야 하는 것 같습니다 .-ttar

$ tar --delete --no-recursion `tar -t --exclude subdir <some.tar` <some.tar | ssh ...

또는 목록이 너무 길거나 복잡한 경우 목록을 외부 파일에 저장할 수 있습니다.

$ tar -t --exclude subdir <some.tar >to_delete.lst
$ tar --delete --no-recursion -T to_delete.lst <some.tar | ssh ...

답변4

내가 아는 한 이 tar명령은 tar 형식으로 사용할 수 없습니다.둘 다입력과 출력으로. 어떻게든 로컬에서 파일을 추출한 다음 tar를 다시 사용하여 다음과 같이 tar 파일을 동적으로 생성해야 합니다(이는 -파일 대신 표준 입력/출력을 사용한다는 의미입니다).

tar cf - subdir/ | ssh remote@system 'cd extractdir && tar xvf -'

다른 tar 파일 내에서 직접 tar 파일을 추출 할 수 있다는 것은 tar흥미로운 아이디어입니다.

관련 정보