私はそう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
(これはファイルリストがtar
1回の呼び出ししか実行できないほど小さいと仮定します。find
隠しファイルはデフォルトでは無視されません。)
答え3
順序が重要な場合。たとえば、アーカイブfoo*
とファイルの両方が必要な場合、ファイルがアーカイブの最初(2回ではない)に表示されるようにしたい*.txt
場合です。 IOW、この順序で:foo*
foo.txt
foo.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
最後であることを確認するには*.txt
(foo.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