.hgignore
Сегодня я пытался быстро отредактировать файл из оболочки Cygwin bash и добавил строку, которая была ошибкой. Я не уверен, что это был лучший способ сделать это, но я быстро подумал об использовании head -1 .hgignore
для удаления ошибочной строки (ранее у меня была только одна строка в файле). Конечно, при выполнении он выдает первую строку в качестве единственного вывода.
Но когда я попытался перенаправить вывод и переписать файл, используя head -1 .hgignore > .hgignore
, файл был пустым. Почему это происходит? Если я попытаюсь добавить вместо этого, head -1 .hgignore >> .hgignore
он добавляется правильно, но это, очевидно, не желаемый результат. Почему усечающее перенаправление не работает в этом случае?
shell
io-redirection
voithos
источник
источник
cut
изменить файл на месте? , Как я могу сделать Iconv заменить входной файл с преобразованным выходом?Ответы:
Когда оболочка получает командную строку, например:
command > file.out
оболочка сама открывает (и, возможно, создает) файл с именемfile.out
. Оболочка устанавливает дескриптор файла 0 равным дескриптору файла, который он получил при открытии. Вот как работает перенаправление ввода / вывода: каждый процесс знает о дескрипторах файлов 0, 1 и 2.Самое сложное в этом - как открыть
file.out
. Большую часть времени вы хотитеfile.out
открыть для записи со смещением 0 (то есть усеченным), и это то, что оболочка сделала для вас. Он обрезал .hgignore, открыл его для записи, дублировал дескриптор файла до 0, а затем выполнилhead
. Мгновенное засорение файлов.В bash shell вы делаете это,
set noclobber
чтобы изменить это поведение.источник
Я думаю, что Брюс отвечает на то, что здесь происходит с конвейером оболочки.
Одна из моих любимых маленьких утилит -
sponge
команда от moreutils . Он решает именно эту проблему, «впитывая» все доступные входные данные, прежде чем открыть целевой выходной файл и записать данные. Это позволяет вам писать конвейеры точно так, как вы ожидали:Решение бедного человека состоит в том, чтобы направить вывод во временный файл, а затем, после того, как закончен трубопровод (например, следующая команда, которую вы выполняете), - переместить временный файл обратно в исходное местоположение файла.
источник
head -1 .hgignore | tee .hgignore
?tee
находится в coreutils, и как перк / побочный эффект, это также пишет в STDOUTtee
открывается и усекается файл, в который он записывается, когда он создается, как и все остальное, поэтому он не решает главную проблему условия гонки при чтении содержимого файла до того, как вы усекаете его с записью.tee
кажется, сделал желаемую вещь. У меня есть версия8.13
на моей машине.tee
Программа будет укоротить ваши файлы, он не настроен на двойной буфер них.В
file
обрезается доhead
запуска, но если вы напишите это:это не так, как
file
открывается в режиме чтения-записи. Однако, когда онhead
завершает запись, он не усекает файл, поэтому строка выше будет неактивной (head
просто перезапишет первую строку поверх себя и оставит остальные нетронутыми).Тем не менее, после того, как
head
вернулось и когдаfd
он все еще открыт, вы можете вызвать другую команду, которая выполняетtruncate
.Например:
Здесь важно то
truncate
, что выше,head
просто перемещает курсор для fd 1 внутри файла сразу после первой строки. Он переписывает первую строку, которая нам не нужна, но это не вредно.С головой POSIX мы могли бы уйти без переписывания первой строки:
Здесь мы используем тот факт, что
head
курсор перемещается в его стандартный ввод. Вhead
то время как обычно для увеличения производительности считываются входные данные, POSIX требует (по возможности)seek
возврата сразу после первой строки, если она вышла за ее пределы. Обратите внимание, что не все реализации делают это.В качестве альтернативы вы можете использовать команду оболочки
read
в этом случае:источник
STDIN
аналогично тому, что вы выполнили, используяperl
вышеdd
может усечь любое произвольное абсолютное смещение в файле, хотя. Таким образом, вы можете определить смещение в байтах второй строки и отсечь оттуда с помощьюdd bs=1 seek="$offset" of=file
Решение настоящего мужчины
или как однострочник
Или с GNU sed:
(Нет, я шучу. Я бы использовал интерактивный редактор.
vi .hgignore
GddZZ
)источник
:wq
болееZZ
?:x
это то, что мои пальцы делают автоматическиZQ
же, как:q!
Вы можете использовать Vim в режиме Ex:
2,
выберите строки 2 до концаd
удалятьx
сохранить и закрытьисточник
Для редактирования файлов на месте вы также можете использовать прием с открытым файлом, как показано Юргеном Хетцелем в перенаправлении вывода из sed 's / c / d /' myFile в myFile .
источник
rm .hgignore
ваша сила выходит из строя, отнимает часы тяжелой работы. Хорошо, это не имеет значения.hgignore
, но зачем вам делать что-то сложное в любом случае? Таким образом, мой недостаток: технически правильная, но очень плохая идея.perl -i
(для редактирования на месте) делает, и я не удивлюсь, если некоторые реализацииsed -i
сделали это также (хотя последняя версия GNU,sed
кажется, не делает ).