tar --excludeは除外しません。どうして?


71

オプションで除外するように指示されたサブディレクトリを除外しないこと_data.tarを除いて、正常に実行する(つまりファイルを生成する)bashスクリプトにこの非常に単純な行があります:--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の下にあるすべてのものを含むファイルを生成します。

理由は何ですか?そして、これを修正する方法は?

更新以下の最初の回答で提供されたリンクに基づいて、観測を実装しました(最初にトップレベルのディレクトリ、最後の除外後に空白なし):

/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'

私が試したものと@Richard Perrinが試したものの間に違いは見られません。ただし、引用符と1の代わりの2つのスペースを除きます。これを試します(バックアップするディレクトリとして夜間スクリプトが実行されるのを待つ必要があります)アップは巨大です)と報告します。

/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スレッドのヒントに従うことを試みていました。何を逃したのかはわかりませんが、2つ目のポイントを読んだので、絶対パスと相対パスの問題になる可能性があります。それを試して報告します。今のところ+1。
-ateiob

もう1つ気づいたのは、--exclude b(等号ではなくスペース)対--exclude=bです。これは違いがありますか?(私見すべきではない)
-ateiob

1
引用符で囲まれていないパターンのシェル拡張を回避するには、等号が不可欠です。代わりにスペースがある場合、引用符で囲まれていないパターンはシェルによって単一の--exclude引数に展開され、残りの展開はtarファイルに追加するファイルとして提供されます。上記の例にはすべて「=」があります。スクリプトに含まれておらず、単一引用符が欠落している場合、それが問題の原因になります。
Rペリン

OK。私のボックスであなたの例をテストし--exclude=ましたが、同じ行に複数ある場合でも動作します。したがって、違いは/*各サブディレクトリに追加したばかげたものでなければなりません。今晩、本番スクリプトでこれをテストし、報告します。もう1つ。
-ateiob

私にとって、@ carloからの答えは特定の問題でした-愚かなtarはコマンドラインの最後のオプションとして--excludeを取ることができません-明らかに多くの頭痛の種を引き起こしています。皆さんありがとう。
moodboom

33

お使いのバージョンでtar--excludetarコマンドの先頭にオプションを配置する必要がある場合があります。

参照: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

参考までに、debianの場合、フィルターを正確に設定しないと、--exclude=mydir/*うまくいきません(を使用tar --exclude=maindir/mydir/* -cjf archive.tar2.bz2 maindir/*)。
オリビエポンズ

1
「debianの下」ではなく@OlivierPons、または恐らくそれとともに、tarのバージョン(tar --version)を置きます。debianはおそらく、長年にわたって多くの異なるバージョンのtarとともに出荷されるでしょう。
-msouth

1
私のバージョン(1.29)は--excludebeforeでのみ動作し-czfます。
falsePockets

8

複数のファイルを除外するには、試してください

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

これにより、いくつかのコードと頭痛の種を節約できます。これは、あらゆる種類のプログラム/オプションに対するグローバルなソリューションです。選択に親ディレクトリも含める場合(この場合はデータ)、末尾のコンマを含める必要があります。例えば:

umount /data/{sub1,sub2,}

3
カーリーが大好きです。多くの人々は、unixの長年の経験があっても、それらについて知らないことがわかります。 mv /very/very/very/very/long/path/to/a/file{,.bak}
-msouth

5

このリンクは役に立つかもしれません。 http://answers.google.com/answers/threadview/id/739467.html

非稼働ラインとリンクのいくつかのヒントとの間の2つの即時の違い:

  1. すべての除外は最上位ディレクトリの後にあります。
  2. 最後の後にスペースを入れることはできません--exclude

ありがとう。答えは-MAK私の注意を引いたし、これまでのところ、私は私の非稼働ラインと、次の次のような違い発見することができました:1.来るすべて除外した後、最上位のディレクトリを。2.最後の後にスペースを入れることはできません--exclude。これらの洞察をテストし、報告します。今のところ+1。
-ateiob

@ateiobわかったら、ここに回答を投稿したり、この回答を編集したりできますか?私たちは、一般的にちょうど別の場所にリンクしている答えを持っていないことを好む
マイケルMrozek

@Michael Mrozek絶対に。これはまさに私のコメントで書いたものです。:)
ateiob

3

この問題を回避するには、の組み合わせを使用することであってもよいfind ... -pruneし、tar指定されたディレクトリを除外すること。

Mac OS Xでは--exclude、GNU のオプションは正常に機能する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でも同様です。
グレッグベル

3

私の場合、別の理由で除外されませんでした。

フルパスと相対パス。

除外とディレクトリの両方で同じパス形式を使用する必要があります(つまり、両方とも完全パスまたは両方の相対パス)

例:

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

excludeはターゲットが相対パスを使用するのにフルパスを使用するため、これは機能しません。

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ペリンの優れた答えへの追加メモ:

たとえば、「/ tmp / data」ではなく「data」など、絶対パスではなく相対パスをアーカイブするとします。絶対パスを除外するには、使用するtarの実装(gnu tarとbsd tar)によって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とzip形式ではない.tgz/ .tar.gzアーカイブ) -あなたは後で使用して、それを圧縮することができますgzip mybackup.tar
  • アーカイブを含めるフォルダーに入れないでください。そうしないと、再帰が発生します(部分的なバックアップもバッ​​クアップ自体に含まれます)。
  • 最初のコマンド(作成)と他のコマンド(追加)の違いに注意してください。
  • を使用して妄想している場合は、バックアップが上書きされるのではなく、ファイルが追加されていることを確認できます(2番目のコマンドの後など)tar tvf mybackup.tar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.