17

Почему перенаправление вывода файла на себя создает пустой файл?

Заявлено в Bash, почему

less foo.txt > foo.txt

а также

fold foo.txt > foo.txt

создать пустой foo.txt? Так как при добавлении, таком как less eggs.py >> eggs.py создается две копии текста в eggs.py , можно ожидать, что при перезаписи будет получена одна копия текста.

Заметьте, я не говорю, что это ошибка, это скорее указатель на что-то глубокое в Unix.

2 ответа2

18

Когда вы используете > , файл открывается в режиме усечения, поэтому его содержимое удаляется до того, как команда попытается его прочитать.

Когда вы используете >> , файл открывается в режиме добавления, поэтому существующие данные сохраняются. Однако в этом случае все еще довольно рискованно использовать один и тот же файл для ввода и вывода. Если файл достаточно велик, чтобы не соответствовать размеру входного буфера чтения, его размер может увеличиваться до бесконечности, пока файловая система не заполнится (или не будет достигнута квота на диске).

Если вы хотите использовать файл как для ввода, так и для вывода с командой, которая не поддерживает модификацию места, вы можете использовать несколько обходных путей:

  • Используйте промежуточный файл и перезаписывайте исходный файл, когда это будет сделано, и только в том случае, если во время работы утилиты не возникло ошибок (это самый безопасный и распространенный способ).

    fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt
    
  • Избегайте промежуточного файла за счет возможной частичной или полной потери данных в случае ошибки или прерывания. В этом примере содержимое foo.txt передается в качестве входных данных в подоболочку (внутри скобок) перед удалением файла. Предыдущий индекс остается активным, поскольку подоболочка сохраняет его открытым во время чтения данных. Файл , написанный на внутреннюю полезность (здесь fold , а с тем же именем foo.txt указует на другой инод , потому что старая запись каталога была удалена , так технически, есть два различные "файлов" с тем же именем во время процесс. Когда подоболочка заканчивается, старый инод освобождается и его данные теряются. Будьте осторожны, чтобы убедиться, что у вас достаточно места для временного хранения как старого файла, так и нового одновременно, иначе вы потеряете данные.

    (rm foo.txt; fold > foo.txt) < foo.txt
    
7

Файл открывается для записи оболочкой до того, как приложение сможет его прочитать. Открытие файла для записи усекает его.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .