管道'找到'到'尾巴`

Har*_*i K 6 linux bash pipe

我想得到查找输出的最后两行并将它们复制到某处.我试过了

find . -iname "*FooBar*" | tail -2 -exec cp "{}" dest \;
Run Code Online (Sandbox Code Playgroud)

但输出是尾部的"无效选项--2".

此外,我的文件或目录名称包含空格.

l0b*_*0b0 5

以下应该适用于任何路径.

声明一个能够使用headtail在NUL分离的输出上的函数:

nul_terminated() {
    tr '\0\n' '\n\0' | "$@" | tr '\0\n' '\n\0'
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用它在通过后从搜索中获取NUL分隔的路径列表tail:

find . -exec printf '%s\0' {} \; | nul_terminated tail -n 2
Run Code Online (Sandbox Code Playgroud)

然后,您可以将其传递给xargs并添加您的选项:

find . -iname "*FooBar*" -exec printf '%s\0' {} \; | nul_terminated tail -n 2 | xargs -I "{}" -0 cp "{}" "dest"
Run Code Online (Sandbox Code Playgroud)

说明:

  1. find当前目录(.)和下面的文件,其名称包含foobar(由于iin 而不区分大小写-iname);
  2. 对于每个文件,运行(-exec)命令
  3. 打印每个文件路径({})后跟一个NUL字符(\0)单独(\;);
  4. 交换换行符和NUL字符(tr '\0\n' '\n\0');"
  5. 拿到最后两行(也就是路径; tail -n 2,"$@");
  6. 再次交换换行符和NUL字符以获取NUL分隔的文件名列表(tr '\0\n' '\n\0').

这个xargs命令有点难以解释.它cp ... "dest"根据需要构建尽可能多的命令以适应操作系统的最大命令长度,使用{}实际文件名(-I "{}" ... "{}")替换命令中的标记,在读取参数(-0)时使用NUL字符作为分隔符.

  • 如果这是一个愚蠢的问题,请原谅我,但我们不应该使用标志`-I`(即:`xargs -I"{}" - 0 cp"{}""dest"`)?(当我尝试没有它似乎没有用.例如:`echo"abc"| xargs echo"{}"def` prints` {} def abc`) (2认同)