web-dev-qa-db-ja.com

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

正常に実行される(つまり、_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の下のすべてを含む_data.tarファイルを生成します。

なぜか?そしてこれを修正するには?

更新以下の最初の回答で提供されたリンクに基づいて、観察結果を実装しました(最上位のディレクトリが最初、最後の除外の後に空白はありません)。

/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のすべての感度はtarではなく、私の環境内の何かであると私は考え始めていますが、それは何でしょうか?

動作しました!試行された最後のバリエーション(--excludes間のダブルスペースの代わりに単一引用符とシングルスペースなし)がテストされ、動作しました。奇妙だが受け入れる。

nbelievable!古いバージョンのtar(1.15.1)は、トップレベルのディレクトリがlastである場合にのみ除外されることがコマンドラインで判明しました。これは、バージョン1.23で必要な方法とは正反対です。ご参考までに。

78
ateiob

ディレクトリ全体を除外する場合、パターンはそのディレクトリ内のファイルではなく、そのディレクトリと一致する必要があります。使用する --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
55
R Perrin

お使いのバージョンの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コマンドのヒントは here からです:

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

複数のファイルを除外するには、

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

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

umount /data/{sub1,sub2,}
8
tolga9009

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

機能していない回線とリンクのいくつかのヒントの間の2つの直接的な違い:

  1. すべての除外は、トップレベルのディレクトリになります。
  2. 最後の--excludeの後にスペースを入れることはできません。
5
BigG

私はMacを使用していますが、最上位のフォルダーが最後の引数でない限り、excludesが機能していませんでした。

作業コマンドの例:

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

ご参考までに:

$: tar --version
bsdtar 2.8.3 - libarchive 2.8.3
5
jars99

おそらく、別のオプションでコマンドを試すことができます。

--wildcards

そして、それが意図したとおりに実行されているかどうかを確認します。

3
Luis

回避策として、find ... -Prunetarの組み合わせを使用して、指定したディレクトリを除外することができます。

Mac OS Xでは、GNU tar--excludeオプションが正常に機能するようです。

次のテストケースでは、ディレクトリ/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
3
jon

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

絶対パスと相対パス。

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

例:

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

どちらも相対パスを使用するため、これは機能します

3
hbt

の代わりに --exclude= 使用する -Xテキストファイル付き:

http://www.cyberciti.biz/faq/exclude-certain-files-when-creating-a-tarball-using-tar-command/

1
Ender

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
Jakob

たった今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}

パラメータの順序は重要です!

1
Alexander