我有一个奇怪的问题参数。
我有一个参数构造不起作用,即使我回显命令,它也能完美运行。我的一行代码如下:
exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'|xargs|xargs -0 -I % pdftk % cat output binder1.pdf
和输出
错误:无法找到文件。错误:无法打开 PDF 文件:20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf
- 选择
exiftool
主题标签中包含单词 DATA 的所有 pdf, - 指示
-p exifprintformat
仅exiftool
打印文件名, - 仅选择
grep
带有 pdf 的行, - 删除
sed
空格, xarg
当我运行
exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'|xargs|xargs -I{} echo pdftk {} cat 输出binder1.pdf
我明白了
pdftk 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf cat 输出活页夹1.pdf
效果非常好。
显然,我做错了……但是是什么呢?
答案1
有几个地方是错误的,而且有不必要的复杂性:-
- 双重
xargs
调用意味着第二个调用看到单行输入,因此{}
只用包含所有匹配文件名的单个字符串替换一次,但echo
不会在输出中显示这种差异(echo a b
与比较echo "a b"
)。 - 该
-0
参数意味着xargs
需要在输入参数之间有一个空字符('\0'
),但是没有;这也强制将输入视为单个参数。 - 通过在条件匹配时仅输出文件名,您将获得每行一个文件名,可以直接通过管道传输而
xargs
无需grep
或sed
。 - 不幸的是,
xargs -I
强制每行输入一个命令,并且没有添加尾随参数的选项,但有一个简单的解决方法:将尾随参数添加到输入流中。
这是一个添加了尾随参数的简化命令(我使用不同的-if
条件进行了测试,没有任何匹配的 PDF):-
{ exiftool -p '${FileName}' -if '$Subject =~/DATA/i' -q *.pdf; \
echo -e "cat\noutput\nbinder1.pdf"; } | xargs -d'\n' pdftk
当文件名中包含空格时,该xargs -d'\n'
选项可使命令起作用。
答案2
xargs 的手册页显示:
-I 替换-str
Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x and -L 1.
换句话说,你最终会得到一个名为“ 20170105170516234.pdf 20170105173126944.pdf 20170105173209758.pdf 20170621163418079.pdf
”的参数
我建议完全放弃 xargs 并重新排序你的命令,如下所示:
pdftk $(exiftool -p exifprintformat -if '$Subject =~/DATA/i' -q *.pdf |grep pdf |sed 's/ //g'| tr '\n' ' ') cat output binder1.pdf
这一切都假设您的文件名中没有空格(安全的假设,因为您无论如何都会使用 sed 删除所有空格)。