使用 tar 过滤重复的文件名

使用 tar 过滤重复的文件名

我像这样使用焦油,

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

问题是pattern1和pattern2有时匹配同一个文件,但tar似乎没有过滤这些重复项。

例如,以下示例在存档中添加两个重复条目

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

我怎样才能过滤掉它们?

答案1

如果pattern1pattern2是 shell 通配符模式,那么您可以使用 or 模式。

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,正确的方法是使用find(这里假设 GNUtar或兼容):

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

(这里假设文件列表足够小,只tar运行一次调用。另请注意,find默认情况下不会忽略隐藏文件)。

答案3

如果顺序很重要。例如,如果您想要存档foo**.txt文件,并且希望foo*文件首先出现在存档中(但foo.txt不包含两次)。 IOW,按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

相关内容