Comment faire `head` et` tail` sur une entrée délimitée par des valeurs nulles dans bash?


18

findLa commande peut afficher les noms de fichiers sous forme de chaînes délimitées par des valeurs nulles (si elles -print0sont fournies) et les xargsconsommer avec l' -0option activée. Mais entre les deux, il est difficile de manipuler cette collection de fichiers - sortcommande a -zcommutateur, qui permet de trier ces fichiers, mais headet tailne les ont pas.

Comment puis-je faire headet tailsur ces entrées délimitées de manière pratique? (Je peux toujours créer un script rubis court et lent, mais j'espère qu'il pourrait y avoir une meilleure façon)

Réponses:


21

GNU headet taildepuis coreutils version 8.25 ont une -zoption pour cela.

Avec des versions plus anciennes ou pour des systèmes non GNU, vous pouvez essayer de permuter \0et \n:

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

Notez que certaines headimplémentations ne peuvent pas faire face à des caractères NUL (et ils ne sont pas requis par POSIX), mais où trouver des appuis -print0, headet les services publics de texte prennent en charge généralement des caractères NUL.

Vous pouvez également utiliser une fonction pour encapsuler n'importe quelle commande entre les deux trs:

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

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

Gardez à l'esprit que sous nul_terminated, un \0signifie un caractère de nouvelle ligne. Ainsi, par exemple, pour remplacer \npar _:

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

( \x0étant également une extension GNU).

Si vous devez exécuter plusieurs commandes de filtrage , vous pouvez effectuer:

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

Mais cela signifie exécuter quelques trcommandes redondantes . Vous pouvez également exécuter:

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

2
Cela ne va-t-il pas à l'encontre de la raison principale¹ d'utiliser \x0plutôt que de \ndélimiter les valeurs? (¹ afin que vous puissiez faire face aux valeurs qui pourraient contenir \n)
Thedward

@Thedward, non, au contraire, -print0 | tr '\n\0' '\0\n'a des lignes représentant les chemins de fichier dans lesquels les caractères de nouvelle ligne ont été convertis \0. Donc, si vous prenez la première ligne avec head -n 1et reconvertissez le \0s en retour à la ligne avec tr '\0\n' '\n\0', vous avez le premier chemin de fichier délimité NUL avec ses caractères de nouvelle ligne incorporés.
Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.