我正在尝试将命令的结果传输find
到 bash 脚本。这是为了简化(或许是自动化)我一直在进行的流程。
这是我想要运行的命令
find . -type f -iname '*.mp4' -exec echo {}|./indexer.sh \;
indexer.sh
是 ofc chmod +x
,因此它可以执行。
indexer.sh
目前包含
#!/bin/zsh
read foo
echo "You entered '$foo'"
如果我运行,$ echo foo | ./indexer.sh
我会得到以下输出
You entered 'foo'
但是当我运行时find . -type f -iname '*.mp4' -exec echo {}|./indexer.sh \;
收到以下错误消息:
find: -exec: no terminating ";" or "+"
You entered ''
那么我怎样才能将 find 的输出导入到我的脚本中呢?
答案1
我将使用参数而不是读取语句和管道来重写它,
find . -type f -iname '*.mp4' -exec ./indexer.sh {} \;
使用以下 indexer.sh,
#!/bin/zsh
echo "You entered '$1'"
答案2
你的误解是它echo {}|./indexer.sh
被视为一个单位。事实并非如此。问题在于你的 shell 将管道解释为前它运行find
。因此,它正在运行……
find . -type f -iname '*.mp4' -exec echo {}
…并将结果传输至
./indexer.sh \;
结果,find
看到{}
没有\;
并且失败。(indexer.sh
看到一个多余的;
参数并忽略它。)
为了纠正你的误解,你必须这样做......
find . -type f -exec sh -c 'echo "{}"|./indexer.sh' \;
...因为这是将该管道视为单个命令的唯一方法。
当然,这太过分了。如果你想indexer.sh
为每个 MP4 文件运行一次,请@sudodus 的建议并彻底避开管道。
答案3
需要\;
放置在管道之前。由于我没有zsh
,并且您的问题带有标签bash
,因此我将使用它bash
作为示例。
索引器
#!/bin/bash
while read foo
do
echo "You entered '$foo'"
done
执行示例
$ find . -type f -iname '*.mp4' -exec echo {} \; |./indexer.sh
You entered './subdirectory/d.mp4'
You entered './subdirectory/c.mp4'
You entered './b.mp4'
You entered './a.mp4'
优化
可以通过删除 find 后面的 和末尾的.
整个部分来优化此 find 用例。如果没有它,find 的输出将是相同的。-exec
$ find -type f -iname '*.mp4' |./indexer.sh
You entered './subdirectory/d.mp4'
You entered './subdirectory/c.mp4'
You entered './b.mp4'
You entered './a.mp4'
答案4
如果你因为某种原因不能或不想改变indexer.sh
,你也可以明确说明你的迭代
find . -type f -iname '*.mp4' | while read file; do echo $file | ./indexer.sh; done
我经常使用这种模式。IFS
如果文件名中有空格,您可能需要设置,但我认为其他解决方案也会遇到同样的问题。