Предупреждение относительно «>»
Новички Unix, которые только что узнали о перенаправлении ввода / вывода ( <и >), часто пробуют такие вещи, как
команда … входной_файл > 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(edit in n place), которую можно использовать для записи вывода обратно во входной файл (опять же, после того , как все входные данные были прочитаны). Редакторы как ed/ ex, emacs, picoи vi/ vim
разрешить пользователю редактировать текстовый файл и сохранить отредактированный текст в исходном файле. Обратите внимание, что ed(по крайней мере) можно использовать не в интерактивном режиме.
viимеет связанную особенность. Если вы напечатаете , он запишет содержимое буфера редактирования в , прочитает вывод и вставит его в буфер (заменяя исходное содержимое).:%!commandEntercommand
Простой, но эффективный:
команда … входной_файл > временный_файл && mv временный_файл входной_файл
Это имеет недостаток, заключающийся в том, что, если 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или -pon, 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 ; } < input_file
Это требует, чтобы commandбыла возможность обрабатывать стандартный ввод (но почти все фильтры могут). Сам блог называет это рискованным препятствием и препятствует его использованию. И это также создаст новый отдельный файл (не связанный ни с чем), принадлежащий вам и с разрешениями по умолчанию.
Пакет moreutils имеет команду под названием sponge:
команда … input_file | губка the_same_file
Смотрите этот ответ для получения дополнительной информации.
Вот что удивило меня:
syntaxerror говорит :
[Большинство из этих решений] завершатся с ошибкой в файловой системе только для чтения, где «только для чтения» означает, что вы $HOME будете доступны для записи, но /tmpтолько для чтения (по умолчанию). Например, если у вас Ubuntu и вы загрузились в консоль восстановления, это обычно так. Кроме того , оператор здесь-документ <<<не будет работать там , либо, так как она требует , /tmpчтобы быть для чтения / записи ,
так как он будет писать временный файл в там.
(ср. этот вопрос включает в себя и straceвывод)
Следующее может работать в этом случае:
Итак, в чем был вопрос?
Это была популярная тема на U & L; он адресован в следующих вопросах:
… И это не считая Super User или Ask Ubuntu. Я включил много информации из ответов на вышеупомянутые вопросы здесь в этом ответе, но не все. (То есть, для получения дополнительной информации, прочитайте перечисленные выше вопросы и ответы на них.)
PS У меня нет связи с блогом, который я цитировал выше.