我正在使用此命令查找可以单独使用的特定文件(2个文件);
find . -iname '*.txt' -o -iname '*.pdf'
并返回正确的文件;
./.folder1/file1.txt
./.folder1/file1.pdf
./.folder2/file2.txt
./.folder2/file2.pdf
但是,如果我尝试将这些已建立的文件制作为tarball,则它仅包含find命令的第一个-iname
部分,就像这样;
find . -iname '*.txt' -o -iname '*.pdf' -print0 | xargs -0 tar -czvf files.tar.gz
因此在此示例中它不包含*.pdf
,而在压缩包中仅包含*.txt
:
./.folder1/file1.txt
./.folder2/file2.txt
如何解决此问题,使*.txt
和*.pdf
都成为压缩包?
答案 0 :(得分:4)
首先,不建议使用find ... | xargs tar -c
:当find
生成文件列表的时间过长,以至于xargs
分成多个tar
调用时,除了最后一次调用将被覆盖。
仅运行tar
的一个副本,并配置那个以便从stdin读取文件要安全得多:
find . '(' -iname '*.txt' -o -iname '*.pdf' ')' -print0 |
tar -c --null -T - -zf backups.tar.gz
编写与您的find
逻辑等效的shell,原始/原始版本可能如下所示:
for f in *; do
{ [[ $f = *.txt ]]; } || \
{ [[ $f = *.pdf ]] && printf '%s\0' "$f"; }
done
如果*.txt
分支为true,则实际上没有完成 ,因为printf
仅以*.pdf
情况为条件。
使用括号将您的分支分组:
find . '(' -iname '*.txt' -o -iname '*.pdf' ')' -print0
...这使逻辑看起来像:
for f in *; do
{ [[ $f = *.txt ]] || [[ $f = *.pdf ]]; } && printf '%s\0' "$f";
done
或在每一侧放置单独的动作副本:
find . -iname '*.txt' -print0 -o -iname '*.pdf' -print0
...的行为类似于
for f in *; do
{ [[ $f = *.txt ]] && printf '%s\0' "$f"; } || \
{ [[ $f = *.pdf ]] && printf '%s\0' "$f"; }
done
答案 1 :(得分:1)
-o
的优先级低于连接-a
和-iname '*.pdf'
的隐式-print0
的优先级。您需要在-o
的括号中加上括号:
find . \( -iname '*.txt' -o -iname '*.pdf' \) -print0
find
仅在根本没有指定 操作的情况下才添加隐式-print
。如果没有括号,则有一个显式-print0
,可以防止将隐式-print
应用于第一个-iname
主变量的结果。