Перенаправлення виводу з усіх команд у файл, а не лише останніх


11

Я хочу додати заголовок у файл із відлунням, а потім скористатися командою, щоб створити решту файлу. Це означає, що я буду використовувати дві окремі команди.

Як записати вихід з обох команд у файл із перенаправленням?

Я намагався

echo "header line" | cut -c 1-5 input_file > output_file

echo "header line"; cut -c 1-5 input_file > output_file

Це лише перенаправляє вихід з команди cut.

Наступна команда працює, але відчуває себе незграбно:

echo "header line" > output_file; cut -c 1-5 input_file >> output_file

Який розумний спосіб вирішити мою проблему?

Відповіді:


11

Проблема тут не проблема з перенаправленням Linux; скоріше, це фундаментальне нерозуміння того, як працює трубопровід. Перенаправлення тут не працює, тому що тільки вирізання насправді друкується до stdout. stdout для команди echo був прокладений для вирізання stdin (який у даному випадку не використовується, оскільки вказаний файл).

echo "header line" > output_file && cut -c 1-5 input_file >> output_file

це те, що ви хочете, і зовсім неелегантний (я замінив вашу ;на &&так, що команда cut буде виконуватися лише в тому випадку, якщо заголовок успішно записаний; таким чином він не буде виконуватись, якщо у вас немає дозволів на створення або запис у output_file ).

Ви також можете зробити все це в передпласті, наприклад.

(echo "header line"; cut -c 1-5 input_file) > output_file

але реальної користі від цього немає, і за допомогою складніших прикладів це може спричинити проблеми, якщо ви не знайомі з визначенням рівня нижньої частини.

Якщо ви хочете вирізати, щоб пройти stdin через stdout, ви можете спробувати:

echo "header line" | cut -c 1-5 - input_file

(Тире - це звичайний ярлик для stdin)

Однак це також виконає операцію зрізання на stdin (в результаті вийде рядок заголовка "header"). Важко сказати, чи це ви хочете чи ні з питання.


13

Що ви шукаєте:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • Цей синтаксис не має побічних ефектів, оскільки команди виконуються в поточній оболонці, а не в підрозділі
  • Існує чітке розмежування команд, які йдуть до файлу output_file
  • Він масштабує добре, тому що ви можете переписати його таким чином:

{
  echo "header line"
  cut -c 1-5 input_file
  ... # insert new commands here
} > output_file

Якщо ви хочете, щоб вихід помилки перейшов до одного файлу, ви можете змінити останній рядок таким чином:

} > output_file 2>&1

Дякуємо Олів'є Дулаку за те, що він нагадав цю пораду.

Якщо ви хочете, щоб якийсь вихід у блоці перейшов на ваш екран, ви можете використовувати цей синтаксис:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file

+1: це зрозуміліше і чітко визначає, що перенаправлено куди. Для того, щоб перенаправити всі ( в тому числі повідомлення про помилку): { .... } > some_file 2>&1(буде «ганчірки» some_file НЕ ганчірки, але запис в нього замість цього, просто змінити. >У >>: { ... } >> some_file 2>&1)
Олів'є Дюлак

4

Тільки, щоб округлити відповіді, є exec.

exec > output_file
echo "header line"
cut -c 1-5 input_file

+1: у сценаріях дуже часто це використовувати (рідше в командному рядку, оскільки речі починають плутати ^^)
Олів'є Дулак

Може хтось детальніше розробив це рішення? Я бачу, що це робить, але я не розумію "exec" у цьому контексті. Крім того, це виглядає як щось, що вам доведеться знову вимкнути, якщо решта вашого сценарію потребує нормальної версії.
Джо

1
коли ви використовуєте exec у скрипті без команди, ви можете зробити перенаправлення вводу / виводу на exec, що впливає на поточну оболонку та всіх майбутніх дітей.
hildred

Спасибі. Я цього раніше не бачив. Я думаю, це буде дуже корисно.
Джо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.