在bash中以空分隔输入如何执行“ head”和“ tail”?


18

find命令可以将文件名输出为以空分隔的字符串(如果-print0提供),并且xargs可以在-0打开选项的情况下使用它们。但是在两者之间,很难对文件进行操作的该集合- sort命令有-z开关,这使得它可能对这些文件进行排序,但headtail没有他们。

我该怎么做head,并tail在一个方便的方式与空分隔的投入?(我总是可以创建一个简短的红宝石脚本,但我希望有更好的方法)

Answers:


21

GNU head以及tail从coreutils版本8.25开始都有一个-z选项。

对于较旧的版本或非GNU系统,您可以尝试交换\0\n

find ... -print0 |
  tr '\0\n' '\n\0' |
  head |
  tr '\0\n' '\n\0'

请注意,有些head实现不能NULL字符处理(和他们不是POSIX要求),但在那里找到支持-print0head并文本实用程序通常支持NULL字符。

您还可以使用函数在两个trs 之间包装任何命令:

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

find ... -print0 | nul_terminated tail -n 12 | xargs -r0 ...

请记住,在下nul_terminated\0表示换行符。因此,例如,替换\n_

find . -depth -name $'*\n*' -print0 | nul_terminated sed '
  p;h;s,.*/,,;s/\x0/_/g;H;g;s,[^/]*\n,,' | xargs -r0n2 mv

\x0也是GNU扩展)。

如果您需要运行多个过滤命令,则可以执行以下操作:

find ... -print0 |
  nul_terminated cmd1 |
  nul_terminated cmd2 | xargs -r0 ...

但这意味着要运行一些冗余tr命令。或者,您可以运行:

find ... -print0 | nul_terminated eval 'cmd1 | cmd2' | xargs -r0 ...

2
这不是打败使用\x0而不是限制\n值的主要理由吗?(¹这样您就可以应对可能包含的值\n
Thedward

@Thedward,没有,相反-print0 | tr '\n\0' '\0\n'具有线表示其中在它们换行字符已被转换到该文件的路径\0。因此,如果您使用的第一行head -n 1并将\0s tr '\0\n' '\n\0'再次转换为换行,则您将获得第一个文件路径NUL分隔,其中包含嵌入的换行符。
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.