bash 管道“查找”到“尾巴”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20936209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:10:02  来源:igfitidea点击:

Piping `find` to 'tail`

linuxbashpipe

提问by Hari K

I want to get the last two lines of the find output and copy them somewhere. I tried

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

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

but the output was "invalid option --2" for tail.

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

Also, my file or directory name contains spaces.

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

采纳答案by l0b0

The following should work on absolutely any paths.

以下应该适用于绝对任何路径。

Declare a function to be able to use headand tailon NUL-separated output:

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

nul_terminated() {
    tr '
find . -exec printf '%s
find . -iname "*FooBar*" -exec printf '%s
cp $(find . -iname "*FooBar*" | tail -2 ) dest
' {} \; | nul_terminated tail -n 2 | xargs -I "{}" -0 cp "{}" "dest"
' {} \; | nul_terminated tail -n 2
\n' '\n
find . -iname "*FooBar*"|tail -n2|xargs -i cp "{}" dest
' | "$@" | tr '
find . -iname "*FooBar*" | tail -n2 | while read file
do
   cp "$file" "$dest"
done
\n' '\n
while IFS=\n read file
' }

Then you can use it to get a NUL-separated list of paths from your search after passing through tail:

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

while read line
do

 cp "$line" dest;

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

You can then pipe that to xargsand add your options:

然后,您可以将其通过管道传输到xargs并添加您的选项:

##代码##

Explanation:

解释:

  1. findfiles in the current directory (.) and below with a name containing foobar(case insensitive because of the iin -iname);
  2. for each file, run (-exec) a command to
  3. print each file path ({}) followed by a NUL character (\0) individually (\;);
  4. swap newlines and NUL characters (tr '\0\n' '\n\0');"
  5. get the last two lines (that is, paths; tail -n 2, "$@");
  6. swap newlines and NUL characters again to get a NUL-separated list of file names (tr '\0\n' '\n\0').
  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')。

The xargscommand is a bit harder to explain. It builds as many cp ... "dest"commands as necessary to fit in the maximum command lengthof the operating system, replacing the {}token in the command with the actual file name (-I "{}" ... "{}"), using the NUL character as a separator when reading the parameters (-0).

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

回答by gturri

You can try

你可以试试

##代码##

回答by Robin Green

##代码##

Unfortunately this won't work with filenames that contain spaces or newlines.

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

回答by David W.

Robin Green:

罗宾·格林:

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

$ find . -iname "*FooBar*"|tail -n2|xargs -i cp "{}" dest
不幸的是,这不适用于包含空格或换行符的文件名。

This will work (at least to the tail) if the file contains spaces. That's because the find will put each file on one line including spaces, tabs, and other special characters.

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

The problem is that xargswill not operate with spaces. You can use the -0or --nulloption with xargs, but that was designed with find ... -print0in mind.

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

What might work is using a whileloop.

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

##代码##

Since you're only reading in one item per line, the $filewill contain the file name with all of the various characters. The only time this will not work is if $filecontains a NL. Then, the tailcommand itself will have issues. Fortunately, having a NL in a file name is quite rare.

由于您每行只读取一个项目,因此$file将包含带有所有不同字符的文件名。唯一不起作用的是如果$file包含 NL。然后,tail命令本身就会有问题。幸运的是,文件名中包含 NL 是非常罕见的。

Some people do this:

有些人这样做:

##代码##

which removes input separators on anything other than a NL, but that shouldn't be necessary.

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

回答by Ashish

Since You file contains 2 lines also have spaces lets keep inverted commas

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

##代码##