我怎样才能让 xargs 对输入做一些事情,然后再做另一件事?

How can I get xargs to do something with the input, then do another thing?

我在 zsh。

我想做这样的事情:

find . -iname *.md | xargs cat && echo "---" > all_slides_with_separators_in_between.md

当然,这会覆盖所有幻灯片,然后在末尾而不是在每张幻灯片之后附加一个“---”。

有 xargs 方法吗?我可以用一些内联函数或 do 块替换 cat && echo "---" 吗?


很奇怪,当我创建一个文件 cat---.sh 内容为

cat 
echo ---

和运行

find . -iname *.md | xargs ./cat---.sh

它只对查找的第一个结果执行。
将 cat---.sh 替换为 cat,并且它在两个文件中都为 运行s。

常见的使用模式是 xargs sh -c 'command; another' _,其中引号中的整个 shell 脚本都可以访问命令行参数。下划线是因为 sh -c 的第一个参数将分配给 [=13=](您经常会在 ps 列表中看到 -sh)。

find . -iname '*.md' |
xargs sh -c 'for x; do
  cat "$x" && echo "---"
done' _ > all_slides_with_separators_in_between.md

如评论中所述,您可能应该调查 find -print0 和 GNU find 中相应的 xargs -0 选项(如果没有,则可以安装它)。

这里完全没有必要使用xargs。以下是一种适当的偏执方法(对带有空格的文件、带有换行符的文件、名称中带有文字反斜杠的文件等具有鲁棒性):

while IFS= read -r -d '' filename; do
  printf '---\n'
  cat -- "$filename"
done < <(find . -iname '*.md' -print0) >all_slides_with_separators.md

然而——你甚至不需要它:find 可以自己完成所有工作,打印分隔符 调用 cat !

find . -iname '*.md' -printf '---\n' -exec cat -- '{}' ';' >all_slides_with_separators.md

你可以这样做,但在某些情况下它可能不安全(见评论):

find . -iname '*.md' | xargs -I % sh -c '{ cat %; echo "----"; }' > output.txt

您在 zsh 中很少需要 find;它的 globbing 设施几乎涵盖了 find.

的所有用例
for f in (#i)**/*.md; do
    cat $f
    print -- "---"
done > all_slides.md

这会以不区分大小写的方式在当前目录层次结构中查找与 *.md 匹配的每个文件。

为了提高效率,将cat $f替换为< $fzsh 本身将读取文件并将其内容写入标准输出。

使用 GNU Parallel 看起来像这样:

parallel cat {}\; print -- --- ::: **/*.md