GNU find "or" 函数不适用于 -print0 | xargs -0 tar
GNU find "or" function is not working with -print0 | xargs -0 tar
我正在使用此命令查找特定文件(2 个文件),这些文件应该可以独立运行;
find . -iname '*.txt' -o -iname '*.pdf'
和returns正确的文件;
./.folder1/file1.txt
./.folder1/file1.pdf
./.folder2/file2.txt
./.folder2/file2.pdf
但是,如果我尝试将这些创建的文件制作成压缩包,它只包含 find 命令的第一个 -iname
部分,如下所示;
find . -iname '*.txt' -o -iname '*.pdf' -print0 | xargs -0 tar -czvf files.tar.gz
所以它不包含此示例中的 *.pdf
s,并且仅包含压缩包中的 *.txt
s:
./.folder1/file1.txt
./.folder2/file2.txt
我该如何解决这个问题,使 *.txt
s 和 *.pdf
s 都成为一个 tarball?
首先,不建议使用 find ... | xargs tar -c
:当 find
生成的文件列表太长以至于 xargs
分成多个 tar
调用时,除了最后一次调用将被覆盖。
运行 更安全,只有一份 tar
,并配置 that 从标准输入读取:
find . '(' -iname '*.txt' -o -iname '*.pdf' ')' -print0 |
tar -c --null -T - -zf backups.tar.gz
编写等同于您的 find
逻辑的 shell,original/buggy 版本可能如下所示:
for f in *; do
{ [[ $f = *.txt ]]; } || \
{ [[ $f = *.pdf ]] && printf '%s[=11=]' "$f"; }
done
如果 *.txt
分支为真,实际上 没有完成 ,因为 printf
仅以 *.pdf
为条件。
使用括号对分支进行分组:
find . '(' -iname '*.txt' -o -iname '*.pdf' ')' -print0
...这使得逻辑看起来像:
for f in *; do
{ [[ $f = *.txt ]] || [[ $f = *.pdf ]]; } && printf '%s[=13=]' "$f";
done
或者在每边放置一个单独的动作副本:
find . -iname '*.txt' -print0 -o -iname '*.pdf' -print0
...这就像:
for f in *; do
{ [[ $f = *.txt ]] && printf '%s[=15=]' "$f"; } || \
{ [[ $f = *.pdf ]] && printf '%s[=15=]' "$f"; }
done
-o
的优先级低于连接 -iname '*.pdf'
和 -print0
的隐式 -a
。您需要将参数括起来 -o
:
find . \( -iname '*.txt' -o -iname '*.pdf' \) -print0
find
如果根本没有指定 操作,则只添加隐式 -print
。没有括号,你有一个显式的 -print0
,它可以防止将隐式的 -print
应用于第一个 -iname
primary.
的结果。
我正在使用此命令查找特定文件(2 个文件),这些文件应该可以独立运行;
find . -iname '*.txt' -o -iname '*.pdf'
和returns正确的文件;
./.folder1/file1.txt
./.folder1/file1.pdf
./.folder2/file2.txt
./.folder2/file2.pdf
但是,如果我尝试将这些创建的文件制作成压缩包,它只包含 find 命令的第一个 -iname
部分,如下所示;
find . -iname '*.txt' -o -iname '*.pdf' -print0 | xargs -0 tar -czvf files.tar.gz
所以它不包含此示例中的 *.pdf
s,并且仅包含压缩包中的 *.txt
s:
./.folder1/file1.txt
./.folder2/file2.txt
我该如何解决这个问题,使 *.txt
s 和 *.pdf
s 都成为一个 tarball?
首先,不建议使用 find ... | xargs tar -c
:当 find
生成的文件列表太长以至于 xargs
分成多个 tar
调用时,除了最后一次调用将被覆盖。
运行 更安全,只有一份 tar
,并配置 that 从标准输入读取:
find . '(' -iname '*.txt' -o -iname '*.pdf' ')' -print0 |
tar -c --null -T - -zf backups.tar.gz
编写等同于您的 find
逻辑的 shell,original/buggy 版本可能如下所示:
for f in *; do
{ [[ $f = *.txt ]]; } || \
{ [[ $f = *.pdf ]] && printf '%s[=11=]' "$f"; }
done
如果 *.txt
分支为真,实际上 没有完成 ,因为 printf
仅以 *.pdf
为条件。
使用括号对分支进行分组:
find . '(' -iname '*.txt' -o -iname '*.pdf' ')' -print0
...这使得逻辑看起来像:
for f in *; do
{ [[ $f = *.txt ]] || [[ $f = *.pdf ]]; } && printf '%s[=13=]' "$f";
done
或者在每边放置一个单独的动作副本:
find . -iname '*.txt' -print0 -o -iname '*.pdf' -print0
...这就像:
for f in *; do
{ [[ $f = *.txt ]] && printf '%s[=15=]' "$f"; } || \
{ [[ $f = *.pdf ]] && printf '%s[=15=]' "$f"; }
done
-o
的优先级低于连接 -iname '*.pdf'
和 -print0
的隐式 -a
。您需要将参数括起来 -o
:
find . \( -iname '*.txt' -o -iname '*.pdf' \) -print0
find
如果根本没有指定 操作,则只添加隐式 -print
。没有括号,你有一个显式的 -print0
,它可以防止将隐式的 -print
应用于第一个 -iname
primary.