Come eseguire `head` e` tail` su input delimitati da null in bash?


18

findIl comando può generare nomi di file come stringhe delimitate da null (se -print0fornite) e xargspuò consumarli con l' -0opzione attivata. Ma in mezzo, è difficile da manipolare che la raccolta di file - sortcomando ha -zinterruttore, che consente di ordinare i file, ma heade tailnon li hanno.

Come posso fare heade tailsu quegli input delimitati da null in modo conveniente? (Posso sempre creare uno script ruby ​​breve e lento, ma spero che ci possa essere un modo migliore)

Risposte:


21

GNU heade taildalla versione 8.25 di coreutils hanno -zun'opzione per questo.

Con versioni precedenti o per sistemi non GNU, puoi provare a scambiare \0e \n:

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

Si noti che alcune headimplementazioni non possono far fronte con caratteri NUL (e non sono tenuti a da POSIX), ma dove trovare appoggi -print0, heade le utility di testo in generale supportare i caratteri NUL.

Puoi anche usare una funzione per avvolgere qualsiasi comando tra i due trs:

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

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

Tieni presente che sotto nul_terminated, \0significa un personaggio newline. Ad esempio, per sostituire \ncon _:

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

( \x0essendo anche un'estensione GNU).

Se è necessario eseguire più di un comando di filtro , è possibile eseguire:

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

Ma questo significa eseguire alcuni trcomandi ridondanti . In alternativa, puoi eseguire:

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

2
Questo non sconfigge il motivo principale¹ per l'utilizzo \x0anziché \nper delimitare i valori? (¹ in modo da poter far fronte a valori che potrebbero contenere \n)
Il

@Thwardward, no, al contrario -print0 | tr '\n\0' '\0\n'ha linee che rappresentano i percorsi dei file in cui sono stati convertiti i caratteri di nuova riga \0. Quindi, se prendi la prima riga con head -n 1e converti \0nuovamente la s in nuove righe tr '\0\n' '\n\0', hai il primo percorso di file delimitato da NUL con i suoi caratteri di nuova riga incorporati.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.