¿Cómo hacer `head` y` tail` en entradas delimitadas por nulos en bash?


18

findEl comando puede generar nombres de archivos como cadenas delimitadas por nulos (si -print0se proporcionan) y xargspuede consumirlos con la -0opción activada. Pero en el medio, es difícil de manipular que la colección de archivos - sortcomandos tiene -zinterruptor, que permite ordenar los archivos, pero heady tailno los tiene.

¿Cómo puedo hacer heady tailen esas entradas delimitadas por nulos de una manera conveniente? (Siempre puedo crear un script de rubí corto y lento, pero espero que pueda haber una mejor manera)

Respuestas:


21

GNU heady taildesde coreutils versión 8.25 tienen una -zopción para eso.

Con versiones anteriores o para sistemas que no son GNU, puede intentar intercambiar \0y \n:

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

Tenga en cuenta que algunas headimplementaciones no pueden hacer frente con caracteres NUL (y que no se les exige que por POSIX), pero donde encontrar apoyos -print0, heady utilidades de texto en general, apoyar caracteres NUL.

También puede usar una función para ajustar cualquier comando entre los dos trs:

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

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

Tenga en cuenta que debajo nul_terminated, a \0significa un personaje de nueva línea. Entonces, por ejemplo, para reemplazar \ncon _:

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

( \x0siendo también una extensión GNU).

Si necesita ejecutar más de un comando de filtrado , puede hacer lo siguiente:

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

Pero eso significa ejecutar algunos trcomandos redundantes . Alternativamente, puede ejecutar:

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

2
¿No vence esto la razón principal primary para usar en \x0lugar de \ndelimitar los valores? (¹ para que pueda hacer frente a los valores que pueden contener \n)
Thedward

@Thedward, no, por el contrario -print0 | tr '\n\0' '\0\n'tiene líneas que representan las rutas de los archivos a los que se han convertido los caracteres de nueva línea \0. Entonces, si toma la primera línea con head -n 1y \0vuelve a convertir la s a líneas nuevas tr '\0\n' '\n\0', tendrá la primera ruta del archivo delimitada por NUL con sus caracteres de línea nueva incrustados.
Stéphane Chazelas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.