Як зробити `голову` та` хвіст` на введенні нуля в баші?


18

findКоманда може виводити імена файлів у вигляді рядків з обмеженим нулем (якщо -print0вони передбачені) та xargsможе споживати їх із -0включеною опцією. Але між ними, це важко маніпулювати , що набір файлів - sortкоманда має -zперемикач, який дає можливість сортувати ці файли, але headі tailїх не має.

Як я можу зробити зручні способи headі tailна цих нульових введеннях? (Я завжди можу створити короткий і повільний рубіновий сценарій, але сподіваюся, що може бути кращий спосіб)

Відповіді:


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реалізації не можуть впоратися з символами NUL (а POSIX їх не вимагає), але там, де знаходять підтримку -print0, headтекстові утиліти зазвичай підтримують символи NUL.

Ви також можете використовувати функцію, щоб обернути будь-яку команду між двома 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-розмежований з вбудованими символами нового рядка.
Stéphane Chazelas
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.