管道'找到'到'尾巴`

时间:2014-01-05 16:44:01

标签: linux bash pipe

我想获取find输出的最后两行并将它们复制到某处。我试过了

find . -iname "*FooBar*" | tail -2 -exec cp "{}" dest \;

但输出是“无效选项--2”尾部。

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

6 个答案:

答案 0 :(得分:5)

以下内容绝对可以用于任何路径。

声明一个能够use head and tail on NUL-separated output的函数:

nul_terminated() {
    tr '\0\n' '\n\0' | "$@" | tr '\0\n' '\n\0'
}

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

find . -exec printf '%s\0' {} \; | nul_terminated tail -n 2

然后,您可以将其传送到xargs并添加选项:

find . -iname "*FooBar*" -exec printf '%s\0' {} \; | nul_terminated tail -n 2 | xargs -I "{}" -0 cp "{}" "dest"

说明:

    当前目录(find)及其下方的
  1. .个文件,其名称包含foobar(因i中的-iname而不区分大小写);
  2. 对于每个文件,运行(-exec)命令
  3. 分别打印每个文件路径({}),然后打印一个NUL字符(\0);
  4. 交换换行符和NUL字符(\;);“
  5. 获取最后两行(即路径; tr '\0\n' '\n\0'tail -n 2);
  6. 再次交换换行符和NUL字符以获取NUL分隔的文件名列表("$@")。
  7. tr '\0\n' '\n\0'命令有点难以解释。它根据需要构建尽可能多的xargs命令以适应操作系统的最大命令长度,将命令中的cp ... "dest"标记替换为实际文件名({{ 1}}),在读取参数({})时使用NUL字符作为分隔符。

答案 1 :(得分:4)

你可以尝试

cp $(find . -iname "*FooBar*" | tail -2 ) dest

答案 2 :(得分:2)

find . -iname "*FooBar*"|tail -n2|xargs -i cp "{}" dest

不幸的是,这不适用于包含空格或换行符的文件名。

答案 3 :(得分:2)

罗宾格林:

  

$ find . -iname "*FooBar*"|tail -n2|xargs -i cp "{}" dest
  Unfortunately this won't work with filenames that contain spaces or newlines.

如果文件包含空格,这将起作用(至少到tail)。这是因为find会将每个文件放在一行上,包括空格,制表符和其他特殊字符。

问题是xargs不能用空格操作。您可以将-0--null选项与xargs一起使用,但设计时考虑到find ... -print0

可能有效的方法是使用while循环。

find . -iname "*FooBar*" | tail -n2 | while read file
do
   cp "$file" "$dest"
done

由于您每行只读一个项目,$file将包含包含所有各种字符的文件名。唯一不行的是$file包含NL。然后,tail命令本身会出现问题。幸运的是,在文件名中使用NL非常罕见。

有些人这样做:

while IFS=\n read file

删除NL以外的任何输入分隔符,但这不是必需的。

答案 4 :(得分:1)

由于你的文件包含2行也有空格让我们保留引号“

while read line
do

 cp "$line" dest;

done < $(find . -iname "*FooBar*" | tail -2)

答案 5 :(得分:0)

我会做的:

find . -iname "filename" -exec tail -n 2 {} \; > output.txt