tar --exclude는 제외되지 않습니다. 왜?


71

나는 (즉이 생산 성공적으로 실행하는 bash는 스크립트에서이 매우 간단 라인이 _data.tar이 점을 제외하고, 파일을) 하지 않는를 통해 제외 이야기하는 하위 디렉토리 제외 --exclude옵션 :

/bin/tar -cf /home/_data.tar  --exclude='/data/sub1/*'  --exclude='/data/sub2/*' --exclude='/data/sub3/*'  --exclude='/data/sub4/*'  --exclude='/data/sub5/*'  /data

대신 _data.tar제외하려는 하위 디렉토리의 파일을 포함하여 / data 아래의 모든 것을 포함 하는 파일을 생성합니다 .

왜 그런지 알아? 이 문제를 해결하는 방법?

업데이트 아래 첫 번째 답변 (최상위 dir 먼저, 마지막 제외 후 공백 없음)에 제공된 링크를 기반으로 관찰을 구현했습니다.

/bin/tar -cf /home/_data.tar  /data  --exclude='/data/sub1/*'  --exclude='/data/sub2/*'  --exclude='/data/sub3/*'  --exclude='/data/sub4/*'  --exclude='/data/sub5/*'

그러나 그것은 도움이되지 못했습니다. 모든 "제외 된"서브 디렉토리가 결과 _data.tar파일에 있습니다.

이것은 수수께끼입니다. 이것이 현재 tar (GNU tar 1.23, CentOS 6.2, Linux 2.6.32의 버그)이든 공백에 대한 tar의 "극단 민감도"및 기타 놓치기 쉬운 오타인지에 관계없이이 버그를 고려합니다. 지금은

이것은 끔찍합니다 . 아래에 제안 된 통찰력을 시도했지만 (후행 없음 /*) 프로덕션 스크립트에서는 여전히 작동하지 않습니다.

/bin/tar -cf /home/_data.tar  /data  --exclude='/data/sub1'  --exclude='/data/sub2'  --exclude='/data/sub3'  --exclude='/data/sub4'

나는 따옴표와 1 대신 2 개의 공백을 제외하고 내가 시도한 것과 @Richard Perrin이 시도한 것 사이의 차이점을 볼 수 없다. 나는 이것을 시도 할 것이다. 위로 올라가고 다시보고하십시오.

/bin/tar -cf /home/_data.tar  /data --exclude=/data/sub1 --exclude=/data/sub2 --exclude=/data/sub3 --exclude=/data/sub4

나는이 모든 tar --exclude민감성이 타르가 아니라 내 환경 에 있다고 생각하기 시작했다 . 그러나 그것은 무엇 일 수 있는가?

효과가 있었다! 마지막으로 시도한 변형 ( --excludes 사이에 이중 공백 대신 작은 따옴표 및 단일 공백 ​​없음 )이 작동하는지 테스트했습니다. 이상하지만 수용.

믿을 수 없는! 이전 버전의 tar(1.15.1)은 최상위 디렉토리가 명령 행에서 마지막 인 경우에만 제외합니다 . 이것은 버전 1.23이 요구하는 것과 정반대입니다. 참고로

답변:


50

전체 디렉토리를 제외 시키려면 패턴이 디렉토리 내의 파일이 아닌 해당 디렉토리와 일치해야합니다. --exclude=/data/sub1대신 사용--exclude='/data/sub1/*'

쉘 확장을 막기 위해 패턴을 인용 할 때주의하십시오.

최종 호출에 문제가있는이 예를 참조하십시오.

$ for i in 0 1 2; do mkdir -p /tmp/data/sub$i; echo foo > /tmp/data/sub$i/foo; done
$ find /tmp/data
/tmp/data
/tmp/data/sub2
/tmp/data/sub2/foo
/tmp/data/sub0
/tmp/data/sub0/foo
/tmp/data/sub1
/tmp/data/sub1/foo
$ tar -zvcf /tmp/_data.tar /tmp/data --exclude='/tmp/data/sub[1-2]'
tar: Removing leading `/' from member names
/tmp/data/
/tmp/data/sub0/
/tmp/data/sub0/foo
$ tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2]
tar: Removing leading `/' from member names
/tmp/data/
/tmp/data/sub0/
/tmp/data/sub0/foo
$ echo tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2]
tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2]
$ tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub[1-2]
tar: Removing leading `/' from member names
/tmp/data/
/tmp/data/sub2/
/tmp/data/sub2/foo
/tmp/data/sub0/
/tmp/data/sub0/foo
/tmp/data/sub2/
tar: Removing leading `/' from hard link targets
/tmp/data/sub2/foo
$ echo tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub[1-2]
tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub1 /tmp/data/sub2

매우 집중되고 명확한 답변에 감사드립니다. 첫 번째 요점과 관련 하여이 LQ 스레드 의 팁을 따르려고했습니다 . 내가 놓친 것이 확실하지 않지만 이제는 두 번째 요점을 읽었으므로 절대 대 상대 경로 문제가 될 수 있습니다. 나는 그것을 시도하고 다시보고합니다. 지금은 +1입니다.
ateiob

내가 주목 한 또 다른 것은 --exclude b(등호 대신 공백) 대 --exclude=b입니다. 이것이 어떤 차이가 있습니까? (IMHO하지 않아야 함)
ateiob

1
인용 부호가없는 패턴의 쉘 확장을 피하려면 등호가 필수적 일 수 있습니다. 대신 공백이 있으면 따옴표로 묶지 않은 패턴을 단일 --exclude 인수로 확장하고 나머지 확장은 tar 파일에 추가 할 파일로 제공합니다. 위의 모든 예제에는 '='가 있습니다-스크립트에 따옴표가 없으면 작은 따옴표가 없으면 문제의 원인이 될 수 있습니다.
R Perrin

승인. 내 상자에서 예제를 테스트 --exclude=했으며 동일한 줄에 여러 개가 있어도 작동 합니다. 따라서 차이점은 /*각 하위 디렉토리에 추가 한 바보 입니다. 오늘 밤 프로덕션 스크립트에서 이것을 테스트하고 다시보고 할 것입니다. 또 다른 +1.
ateiob 2019

저에게 @carlo의 대답은 멍청한 타르가 취할 수없는 특정 문제였습니다-명령 줄의 마지막 옵션으로 제외하십시오-분명히 많은 두통을 유발합니다. 모두 감사합니다.
moodboom

32

이 버전이 있다고 할 수있다 tar해야합니다 --exclude옵션의 시작 부분에 배치해야 할 tar명령.

참조 : https://stackoverflow.com/q/984204

tar --exclude='./folder' --exclude='./upload/folder2' \
    -zcvf /backup/filename.tgz .

참조 : http://mandrivausers.org/index.php?/topic/8585-multiple-exclude-in-tar/

tar --exclude=<first> --exclude=<second> -cjf backupfile.bz2 /home/*

대안 :

EXCLD='first second third'
tar -X <(for i in ${EXCLD}; do echo $i; done) -cjf backupfile.bz2 /home/*

또 다른 tar명령 팁은 다음과 같습니다 .

tar cvfz myproject.tgz --exclude='path/dir_to_exclude1' \
                       --exclude='path/dir_to_exclude2' myproject

위의 내 업데이트를 참조하십시오. 마지막으로 시도한 변형 (따옴표없이 단일 공백)이 작동합니다. 왜 그런지 모르겠습니다. 잘 생각 된 답변 + 링크 +1
ateiob

참고로, 데비안에서 필터를 정확하게 작성하지 않으면 --exclude=mydir/*작동하지 않습니다 (을 사용하여 tar --exclude=maindir/mydir/* -cjf archive.tar2.bz2 maindir/*).
Olivier Pons

1
@debian이 아닌 @OlivierPons 또는 아마도 그것과 함께 tar ( tar --version) 버전을 넣으십시오 . 데비안은 아마도 여러 해에 걸쳐 다양한 버전의 타르와 함께 제공 될 것입니다.
msouth

1
내 버전 (1.29)은 --excludebefore 에서만 작동합니다 -czf.
falsePockets

8

여러 파일을 제외하려면

--exclude=/data/{sub1,sub2,sub3,sub4}

코드와 두통이 줄어 듭니다. 이것은 모든 종류의 프로그램 / 옵션을위한 글로벌 솔루션입니다. 선택에 상위 디렉토리 (이 경우 데이터)를 포함하려면 후행 쉼표를 포함해야합니다. 예 :

umount /data/{sub1,sub2,}

3
나는 curlies를 좋아한다. 수년간의 유닉스 경험으로도 많은 사람들이 그들에 대해 알지 못한다는 것을 알게되었습니다. mv /very/very/very/very/long/path/to/a/file{,.bak}
msouth

5

이 링크가 도움이 될 수 있습니다. http://answers.google.com/answers/threadview/id/739467.html

작동하지 않는 라인과 링크의 몇 가지 팁 사이의 즉각적인 차이점 두 가지 :

  1. 모든 제외는 최상위 디렉토리 다음에 옵니다.
  2. 마지막 뒤에 공백이있을 수 없습니다 --exclude.

감사. 대답은 -MAK내주의를 끌었으며 지금까지는 작동하지 않는 회선과 다음의 차이점을 발견 할 수있었습니다. 1. 모든 제외 항목은 최상위 디렉토리 뒤에 옵니다. 2. 마지막 뒤에 공백이 없어야합니다 --exclude. 이러한 통찰력을 테스트하고 다시보고하겠습니다. 지금은 +1입니다.
ateiob

@ateiob 알아 낸 경우 여기에 답변을 게시하거나이 답변을 편집 할 수 있습니까? 우리는 일반적으로 다른 곳의 링크 인 답변을 선호하지 않습니다
Michael Mrozek

@Michael Mrozek 물론입니다. 이것은 내 의견에 정확히 쓴 것입니다. :)
ateiob

3

해결 방법의 조합을 사용할 수 있습니다 find ... -prunetar지정된 디렉토리를 제외 할 수 있습니다.

Mac OS X에서는 --excludeGNU 옵션이 정상적으로 tar작동하는 것 같습니다.

다음 테스트 사례에서 디렉토리 /private/var/log/asl와 디렉토리 /private/var/log/DiagnosticMessages의 압축 된 아카이브에서 제외됩니다 /private/var/log.

# all successfully tested in Bash shell on Mac OS X (using gnutar and gfind)

# sudo port install findutils  # for gfind from MacPorts

sudo gnutar -czf ~/Desktop/varlog.tar.gz /private/var/log --exclude "/private/var/log/asl" --exclude "/private/var/log/DiagnosticMessages"

sudo gnutar -czf ~/Desktop/varlog.tar.gz  --exclude "/private/var/log/asl" --exclude "/private/var/log/DiagnosticMessages" /private/var/log

set -f # disable file name globbing
sudo gnutar -czf ~/Desktop/varlog.tar.gz  --exclude "/private/var/log/asl" --exclude "/private/var/log/Diagnostic*" /private/var/log

# combining GNU find and tar (on Mac OS X)

sudo gfind /private/var/log -xdev -type d \( -name "asl" -o -name "DiagnosticMessages" \) -prune -o -print0 | 
   sudo gnutar --null --no-recursion -czf ~/Desktop/varlog.tar.gz --files-from -

# exclude even more dirs
sudo gfind /private/var/log -xdev -type d \( -name "asl" -o -name "[Dacfks]*" \) -prune -o -print0 | 
    sudo gnutar --null --no-recursion -czf ~/Desktop/varlog.tar.gz --files-from -


# testing the compressed archive

gnutar -C ~/Desktop -xzf ~/Desktop/varlog.tar.gz

sudo gfind /private/var/log ~/Desktop/private \( -iname DiagnosticMessages -or -iname asl \)

sudo rm -rf ~/Desktop/varlog.tar.gz ~/Desktop/private

제안에 대해 +1 감사합니다. 이 시점에서 나는 여전히 잘 문서화 된 (그리고 성숙한) 기능이 cron에 의해 야간 실행되는 스크립트에서 작동하지 않는 이유를 이해하려고 노력하고 있습니다.
ateiob

3

다른 옵션으로 명령을 시도 할 수도 있습니다.

--wildcards

의도 한대로 실행되고 있는지 확인하십시오.


위의 내 업데이트를 참조하십시오. 마지막으로 시도한 변형 (따옴표없이 단일 공백)이 작동합니다. 왜 그런지 모르겠습니다. 아이디어에 +1
ateiob

3

Mac을 사용하고 있는데 최상위 폴더가 마지막 인수가 아닌 한 제외가 작동하지 않는 것으로 나타났습니다.

작업 명령의 예 :

tar czvf tar.tgz --exclude='Music' dir

참고 사항 :

$: tar --version
bsdtar 2.8.3 - libarchive 2.8.3

Ubuntu 14.04를 통해 tar 1.27.1도 마찬가지입니다.
Greg Bell

3

제 경우에는 다른 이유로 배제하지 않았습니다.

전체 경로와 상대 경로

제외와 디렉토리는 모두 동일한 경로 형식을 사용해야합니다 (예 : 전체 경로 또는 두 상대 경로)

예:

tar -cvf ctms-db-sync.tar --exclude='/home/mine/tmp/ctms-db-sync/sql' ctms-db-sync

제외는 대상이 상대 경로를 사용하는 전체 경로를 사용하기 때문에 작동하지 않습니다.

tar -cvf ctms-db-sync.tar --exclude='/home/mine/tmp/ctms-db-sync/sql' /home/mine/tmp/ctms-db-sync

둘 다 전체 경로를 사용하기 때문에 작동합니다.

tar -cvf ctms-db-sync.tar --exclude='ctms-db-sync/sql' ctms-db-sync

둘 다 상대 경로를 사용하기 때문에 작동합니다.



1

R Perrin의 탁월한 답변에 대한 추가 참고 사항 :

절대 경로가 아닌 상대 경로 (예 : '/ tmp / data'대신 'data')를 아카이브하지 않으려한다고 가정하십시오. 절대 경로를 제외하기 위해 tar 인수는 사용하는 tar 구현 (gnu tar와 bsd tar)에 따라 다릅니다.

$ for i in 0 1 2; do
    for j in 0 1 2; do 
      mkdir -p /tmp/data/sub$i/sub$j
      echo foo > /tmp/data/sub$i/sub$j/foo
    done
  done

$ find /tmp/data/
/tmp/data/
/tmp/data/sub2
/tmp/data/sub2/sub2
/tmp/data/sub2/sub2/foo
/tmp/data/sub2/sub1
/tmp/data/sub2/sub1/foo
/tmp/data/sub2/sub0
/tmp/data/sub2/sub0/foo
/tmp/data/sub1
/tmp/data/sub1/sub2
/tmp/data/sub1/sub2/foo
/tmp/data/sub1/sub1
/tmp/data/sub1/sub1/foo
/tmp/data/sub1/sub0
/tmp/data/sub1/sub0/foo
/tmp/data/sub0
/tmp/data/sub0/sub2
/tmp/data/sub0/sub2/foo
/tmp/data/sub0/sub1
/tmp/data/sub0/sub1/foo
/tmp/data/sub0/sub0
/tmp/data/sub0/sub0/foo

$ cd /tmp/data; tar -zvcf /tmp/_data.tar --exclude './sub[1-2]'
./
./sub0/
./sub0/sub2/
./sub0/sub2/foo
./sub0/sub1/
./sub0/sub1/foo
./sub0/sub0/
./sub0/sub0/foo

# ATTENTION: bsdtar's behaviour differs from traditional tar (without a leading '^')!
$ cd /tmp/data; bsdtar -zvcf /tmp/_data.tar --exclude './sub[1-2]' .
a .
a ./sub0
a ./sub0/sub0
a ./sub0/sub0/foo

# FIX: Use a regex by adding a leading '^' will cause bsdtar to match only parent files and folders.
$ cd /tmp/data; bsdtar -zvcf /tmp/_data.tar --exclude '^./sub[1-2]' .
# ALTERNATIVE: bsdtar -C /tmp/data -zvcf /tmp/_data.tar --exclude '^./sub[1-2]' .
a .
a ./sub0
a ./sub0/sub2
a ./sub0/sub1
a ./sub0/sub0
a ./sub0/sub0/foo
a ./sub0/sub1/foo
a ./sub0/sub2/foo

1

방금 tar (GNU tar) 1.29에서 감지되었습니다.

이 호출은 --exclude-from으로 지정된 아카이브 파일에서 제외되지 않습니다.

/bin/tar --files-from ${datafile} --exclude-from ${excludefile} -jcf ${backupfile}

이 호출은 공동으로 작동합니다.

/bin/tar --exclude-from ${excludefile} --files-from ${datafile} -jcf ${backupfile}

매개 변수의 순서가 중요합니다!


0

나열된 답변 중 일부를 포함하여 모든 종류의 조합을 시도했지만 나열된 파일을 제외시킬 수 없었습니다.

그래서 5 분 동안해야 할 일에 대한 답을 쫓는 것에 반대하면서 나는 그 반대를했습니다. 내가 포함하고 싶은 폴더의 아카이브를 만들었습니다 .

아카이브를 만든 다음 추가 하여이 작업 을 수행했습니다 .

tar -cvpf /path/to/mybackup.tar ./bin
tar rvf /path/to/mybackup.tar ./boot
tar rvf /path/to/mybackup.tar ./etc
tar rvf /path/to/mybackup.tar ./home
tar rvf /path/to/mybackup.tar ./lib
tar rvf /path/to/mybackup.tar ./sbin
tar rvf /path/to/mybackup.tar ./usr
tar rvf /path/to/mybackup.tar ./var

몇 가지 참고 사항 :

  • 파일 시스템의 루트에서 실행하여 문제를 일으키는 절대 경로 대신 상대를 사용했습니다.
  • tar압축 된 tar .tgz/ .tar.gz)가 아닌 일반 아카이브 를 작성해야 합니다. 나중에 다음을 사용하여 압축 할 수 있습니다.gzip mybackup.tar
  • 포함하는 폴더에 아카이브를 두지 마십시오. 그렇지 않으면 일부 재귀 (백업 자체에 포함 된 부분 백업)가 나타납니다.
  • 첫 번째 명령 (만들기)과 다른 명령들 (추가)의 차이점에 유의하십시오.
  • 를 사용하여 편집증 인 경우 백업을 덮어 쓰지 않고 (예 : 두 번째 명령 이후) 파일이 추가되고 있는지 확인할 수 있습니다 tar tvf mybackup.tar.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.