Попередження щодо ">"
Початківці Unix, які щойно дізналися про перенаправлення вводу / виводу ( <
і >
), часто пробують такі речі
команда ... input_file > the_same_file
або
команда … < файл > the_same_file
або, майже рівнозначно,
файл котів | команда …> the_same_file
( grep
, sed
, cut
, sort
, І spell
приклади команд , які люди схильні використовувати в конструкціях , як ці.) Користувачі здивовані, виявивши , що ці сценарії призводять до файлу стають порожнім.
Нюанс, який, мабуть, не згадується в іншій відповіді, можна знайти в першому реченні розділу « Перенаправлення» bash (1) :
Перед виконанням команди його введення та вихід можуть бути перенаправлені
за допомогою спеціального позначення, інтерпретованого оболонкою.
Перші п’ять слів мають бути жирними, курсивними, підкресленими, збільшеними, блимаючими, кольоровими червоними кольорами та позначеними значком, щоб підкреслити той факт, що оболонка виконує запитувані переадресації
перед виконанням команди . І пам’ятайте також
Перенаправлення виводу призводить до відкриття файла… для запису…. Якщо файл не існує, він створюється; якщо він існує, він обрізаний нульовим розміром.
Отже, у цьому прикладі:
sort roster > roster
оболонка відкриває roster
файл для запису, обрізає його (тобто відкидає весь його вміст), перш ніж sort
програма почне працювати. Природно, нічого не можна зробити для відновлення даних.
Можна наївно цього очікувати
tr "[:upper:]" "[:lower:]" < poem > poem
може бути і краще. Оскільки оболонка обробляє перенаправлення зліва направо, вона відкривається poem
для читання (для tr
стандартного вводу), перш ніж відкривати її для запису (для стандартного виводу). Але це не допомагає. Незважаючи на те, що ця послідовність операцій дає дві ручки файлів, вони обидва вказують на один і той же файл. Коли оболонка відкриває файл для читання, вміст все ще є, але вони все ще заблокуються перед виконанням програми.
Отже, що з цим робити?
Рішення включають:
Перевірте, чи має програма, яку ви запускаєте, власну, внутрішню, можливість визначати, куди йде вихід. На це часто вказують -o
(або --output=
) маркер. Зокрема,
sort roster -o roster
приблизно еквівалентний
sort roster > roster
крім того, у першому випадку sort
програма відкриває вихідний файл. І це не досить , щоб відкрити вихідний файл розумного , поки після того, як вона прочитала все вхідний файл (ів).
Аналогічно, принаймні деякі версії sed
мають опцію -i
(редагувати i n місце), яку можна використовувати для запису виводу у вхідний файл (знову ж таки, після того , як всі дані будуть прочитані). Редактори як ed
/ ex
, emacs
, pico
і vi
/ vim
дозволити користувачеві редагувати текстовий файл і зберегти відредагований текст у вихідному файлі. Зауважте, що ed
(принаймні) можна використовувати неінтерактивне.
vi
має пов’язану особливість. Якщо ви введете текст , він запише вміст буфера редагування , прочитає вихід та вставить його в буфер (замінивши вихідний вміст).:%!command
Entercommand
Простий, але ефективний:
команда … input_file > temp_file && mv temp_file input_file
У цьому є недолік, що якщо input_file
посилання є, воно (ймовірно) буде замінено окремим файлом. Також новим файлом будете володіти вами із захистом за замовчуванням. Зокрема, це несе в собі ризик того, що файл буде прочитаний у всьому світі, навіть якщо оригіналу цього input_file
не було.
Варіації:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
що все-таки (потенційно) покине temp_file
світоглядний. Навіть краще:
cp input_file temp_file && command … temp_file > input_file && rm temp_file
Вони зберігають стан посилання, власника та режим (захист) файлу, потенційно ціною вдвічі більше вводу / виводу. (Ви , можливо , буде потрібно використовувати опцію , як -a
або -p
на , cp
щоб сказати йому , щоб зберегти атрибути.)
command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(розбивається на окремі рядки лише для читабельності) Це зберігає режим файлу (і, якщо ви root, власник), але робить його власником вас (якщо ви не root), і робить його новим, окремий файл.
Цей блог
("На місці" редагування файлів) пропонує та пояснює
{rm input_file && command …> input_file ; } < вхідний_файл
Це вимагає, щоб command
мати можливість обробляти стандартний вхід (але майже всі фільтри можуть). Сам блог називає це ризикованою суєтою і відштовхує від її використання. І це також створить новий окремий файл (не пов’язаний ні з чим), який належить вам та має дозволи за замовчуванням.
У пакеті moreutils є команда під назвою sponge
:
команда … input_file | губка the_same_file
Дивіться цю відповідь для отримання додаткової інформації.
Ось щось, що стало для мене повним сюрпризом:
syntaxerror говорить :
[Більшість з цих рішень] відбудеться збій в файлової системі тільки для читання, де «тільки для читання» означає , що ваш $HOME
буде мати права на запис, але /tmp
буде доступний тільки для читання (за замовчуванням). Наприклад, якщо у вас є Ubuntu, і ви завантажилися в консоль відновлення, це зазвичай так. Крім того , оператор тут-документ <<<
не працюватиме там , або, так як вона вимагає , /tmp
щоб бути для читання / запису ,
так як він буде писати тимчасовий файл в там.
(пор. це питання включає в себе strace
'd вихід)
У цьому випадку може працювати наступне:
Отже, про що було питання?
Це була популярна тема щодо U&L; Він розглядається в наступних питаннях:
… І це не враховує Super User або Ask Ubuntu. Я включив у цю відповідь багато інформації з відповідей на вищезазначені питання, але не всю. (Тобто, для отримання додаткової інформації прочитайте вищеперелічені питання та їх відповіді.)
PS Я не маю приналежності до блогу, який я цитував вище.