파이프에 다른 tar 파일을 생성하여 tar 파일의 내용을 필터링하려면 어떻게해야합니까?


13

권한, mtimes 등과 같이 유지하려는 다양한 속성을 가진 일부 디렉토리를 포함하는 외부 시스템의 단일 tar 파일을 고려하십시오. 이러한 파일의 서브 세트를 루트가 아닌 일반 사용자로 쉽게 가져올 수 있습니까?

다음과 같은 것을 찾고 있습니다.

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

또한이 tar 아카이브의 주요 속성 (소유권, 그룹, 모드, mtime)을 유지해야합니다. 확장 헤더 키워드 와 같은 tar 파일의 다른 속성은 어떻습니까?

이 하위 디렉토리에 대용량 파일이 포함 된 경우 임시 디렉토리를 사용하지 않는 솔루션에 대한 보너스 포인트.

답변:


14

bsdtar (libarchive 기반 )는 stdin에서 stdout으로 tar (및 기타 아카이브)를 필터링 할 수 있습니다. 예를 들어 패턴과 일치 하는 파일 이름 만 통과 하고 s/old/new/이름을 바꿀 수 있습니다 . bsdtarUbuntu 와 같이 대부분의 배포판에 이미 패키지되어 있습니다.

sudo apt-get install bsdtar   # 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에 사용할 수 있습니다 .


내 검색에서도 javascript를 사용하여 원하는 아카이브 변경 사항을 정의하려는이 스트리밍 tar 수정 도구를 찾았습니다. (모든 것이 js로 작성되었다고 생각합니다).

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


1
훌륭합니다.이 @original.tar접근법이 bsdtar로 가능하다는 것을 몰랐습니다. 확장 된 속성 및 압축에서도 작동하는 것 같습니다 </var/cache/pacman/pkg/libuv-1.7.0-1-x86_64.pkg.tar.xz bsdtar -czf - --include='usr/share/*' @- | tar tvz(어떤 이유로 빈 선택은 일련의 0 바이트를 생성하지만 큰 문제는 아닙니다).
Lekensteyn

1
내 테스트에 따르면 @ old.tgz를 사용하여 오래된 아카이브에서 온 파일 s/old/new/ 에서는 작동 하지 않으며 파일 시스템에서 직접 보관하는 실제 파일에서만 작동합니다. 그것은 나에게 가장 유용한 유스 케이스 일 것이므로 부끄러운 일입니다.
bart

4

가장 쉬운 방법은 전체 아카이브를 복사하는 것입니다. 나는 그것이 너무 커서 그렇게하고 싶지 않다고 가정합니다.

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

소유권을 유지할 필요가 없다면 FUSE 파일 시스템을 사용하는 것이 좋습니다 . archivemount 를 사용 하여 아카이브를 파일 시스템으로 마운트 할 수 있습니다 . 소스 아카이브에 대해이를 수행하고 마운트 된 파일 시스템에서 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라이브러리는 타르 멤버를 조작하는 상당히 쉬운 방법을 제공하므로, 하나의 타르 파일에서 다른 타르 파일로 셔플 할 수 있습니다. POSIX 표준 형식 (ustar, pax) 및 일부 GNU 확장을 지원합니다. 다음은 표준 입력에서 tar 파일 (gzip 또는 bzip2로 압축 됨)을 읽고 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

1
bsdtar (libarchive 기반)는 tar 아카이브를 즉시 필터링 할 수 있습니다. 내 답변을 참조하십시오.
Peter Cordes

작업은 펌웨어 이미지에서 데이터를 추출하는 것이 었으므로 소유권 / 그룹 멤버쉽이 중요합니다. 파이썬 접근법이 작동 할 수 있습니다.
Lekensteyn

0

다른 권한없는 접근 방법은 fakeroot프로그램을 사용하여 소유권을 변경할 수있는 척하는 것입니다. 다른 tar 속성은 손실되지만 모드, mtime 및 uid / gid는 유지합니다. 이 명령은 임시 디렉토리를 작성하고 파일의 서브 세트를 추출한 후 마지막으로 새 아카이브를 작성합니다.

mkdir tmp
<some.tar.gz \
fakeroot -- sh -c 'cd tmp && tar -xzf- subdir/ && tar -czf- subdir' |
   ssh remote@system tar -xzvf-
rm -rf tmp

0

GNU tar에는 --delete옵션이 있습니다 :

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

이런 식으로, 출력에 포함 하지 않을 것을 지정하여 입력 tar의 서브 세트를 얻을 수 있습니다 .

불행히도 --exclude작업 할 수있는 옵션을 얻을 수 없으므로 --delete먼저 -t삭제할 항목의 명시 적 목록을 가져온 다음 다른 호출로 전달해야합니다 tar.

$ 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 ...

-1

내가 무엇을 알고 있으며,이 tar명령은 tar 형식을 사용할 수 없습니다 모두 입력 및 출력한다. 어떻게 든 파일을 로컬로 추출하고 tar를 다시 사용하여 tar 파일을 즉석에서 작성해야합니다 ( -즉, 파일 대신 표준 입 / 출력이 사용됨).

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

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


루트가 없으면 명시 적으로 유지하려는 모든 소유권 / 그룹 정보가 손실됩니다.
Lekensteyn

1
호스트에 대한 루트 액세스 권한이 없음을 포함하도록 질문을 편집해야합니다.
Uriel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.