Como fazer 'head' e 'tail' na entrada delimitada por nulo no bash?

17
O comando

find pode gerar nomes de arquivos como strings delimitadas por nulo (se -print0 for fornecido) e xargs puder consumi-los com a opção -0 ativada. Mas, no meio, é difícil manipular essa coleção de arquivos - o comando sort tem -z switch, o que torna possível classificar esses arquivos, mas head e tail não os têm.

Como posso fazer head e tail nessas entradas delimitadas por nulos de uma maneira conveniente? (Eu sempre posso criar um script curto e lento ruby, mas espero que possa haver uma maneira melhor)

    
por Rogach 09.05.2013 / 05:06

1 resposta

20

GNU head e tail desde a versão 8.25 do coreutils tem uma opção -z para isso.

Com versões mais antigas ou para sistemas não-GNU, você pode tentar trocar \n e head :

find ... -print0 |
  tr '
nul_terminated() {
  tr '
find . -depth -name $'*\n*' -print0 | nul_terminated sed '
  p;h;s,.*/,,;s/\x0/_/g;H;g;s,[^/]*\n,,' | xargs -r0n2 mv
\n' '\n
find ... -print0 |
  nul_terminated cmd1 |
  nul_terminated cmd2 | xargs -r0 ...
' | "$@" | tr '
find ... -print0 | nul_terminated eval 'cmd1 | cmd2' | xargs -r0 ...
\n' '\n
find ... -print0 |
  tr '
nul_terminated() {
  tr '
find . -depth -name $'*\n*' -print0 | nul_terminated sed '
  p;h;s,.*/,,;s/\x0/_/g;H;g;s,[^/]*\n,,' | xargs -r0n2 mv
\n' '\n
find ... -print0 |
  nul_terminated cmd1 |
  nul_terminated cmd2 | xargs -r0 ...
' | "$@" | tr '
find ... -print0 | nul_terminated eval 'cmd1 | cmd2' | xargs -r0 ...
\n' '\n%pre%' } find ... -print0 | nul_terminated tail -n 12 | xargs -r0 ...
\n' '\n%pre%' | head | tr '%pre%\n' '\n%pre%'
' } find ... -print0 | nul_terminated tail -n 12 | xargs -r0 ...
\n' '\n%pre%' | head | tr '%pre%\n' '\n%pre%'

Note que algumas implementações -print0 não podem lidar com caracteres NUL (e não são obrigados a fazê-lo pelo POSIX), mas onde encontrar suporta head , tr e utilitários de texto geralmente suportam caracteres NUL.

Você também pode usar uma função para agrupar qualquer comando entre os dois nul_terminated s:

%pre%

Lembre-se de que, em \n , um _ significa um caractere de nova linha. Por exemplo, para substituir \x0 por tr :

%pre%

( %code% sendo também uma extensão GNU).

Se você precisar executar mais de um filtro comando, você pode fazer:

%pre%

Mas isso significa executar alguns comandos %code% redundantes. Como alternativa, você pode executar:

%pre%     
por 09.05.2013 / 09:45