tarを使用した重複ファイル名のフィルタリング

tarを使用した重複ファイル名のフィルタリング

私はそうtarを使用する。

tar -cjpvf a.tar "$pattern1" "$pattern2"

問題は、パターン1とパターン2が時々同じファイルと一致しますが、tarはこれらの重複項目をフィルタリングしないようです。

たとえば、次の例では、アーカイブに2つの重複エントリを追加します。

%> tar -cjpvf a.tar /etc/passwd /etc/passwd
%> tar -xvf a.tar
etc/passwd
etc/passwd

どのようにフィルタリングできますか?

答え1

pattern1がシェルワイルドカードパターンの場合、pattern2またはパターンを使用できます。

tar -cjpvf a.tar @($pattern1|$pattern2)

これにはksh、bash、またはzshが必要です。 Bashでは、パターン構文をshopt -s extglob有効にするには実行する必要があります。@(…)zshでは、setopt ksh_glob最初に実行するか(zshに変数に文字列の代わりにパターンが含まれていることを知らせる@($~pattern1|$~pattern2))、デフォルトの構文を使用する必要があります($~pattern1|$~pattern2)

答え2

解析された出力が好きな場合ls(すべてのファイル名に文字やワイルドカードが含まれていないか、$IFSで始まると仮定します-):

tar -cjpvf a.tar $(ls -d1 <pattern1> <pattern2> | sort | uniq)

または

tar -cjpvf a.tar $(ls -d1 <pattern1> <pattern2> | sort -u)

出力を解析するのに慣れていない場合は、ls正しい方法は次のものを使用することです(GNUまたは互換性があるとfind仮定)。tar

find -maxdepth 1 \( -name <pattern1> -o -name <pattern2> \) -print0 \
 | xargs -0 tar -cjpvf a.tar

(これはファイルリストがtar1回の呼び出ししか実行できないほど小さいと仮定します。find隠しファイルはデフォルトでは無視されません。)

答え3

順序が重要な場合。たとえば、アーカイブfoo*とファイルの両方が必要な場合、ファイルがアーカイブの最初(2回ではない)に表示されるようにしたい*.txt場合です。 IOW、この順序で:foo*foo.txtfoo.a foo.b foo.txt foo.z a.txt b.txt z.txt

そしてzsh

files=(./foo*(N) ./*.txt(N))
(($#files)) && tar jcf file.tar.bz2 ${(u)files}

そしてtcsh

set -f files = (./foo* ./*.txt) && tar jcf file.tar.gz2 $files:q

最後であることを確認するには*.txtfoo.a foo.b foo.z a.txt b.txt foo.txt z.txt順番に):

そしてzsh

files=(./foo*(N) ./*.txt(N))
(($#files)) && tar jcf file.tar.bz2 ${(uOa)${(Oa)files}}

Oaパラメータ拡張フラグで配列の順序を逆にします。)

そしてtcsh

set -l files = (./foo* ./*.txt) && tar jcf file.tar.gz2 $files:q

関連情報