Comments 16
0<
== <
, >file
перенаправляет вывод в файл, затирая прошлое содержимое, а >>file
добавляет в конец. А то в первом скрипте >
, а дальше пошли >>
Прошу прощения, если что-то пропустил в тексте.
Остался разве что аргумент в пользу читабельности ( cat /dev/null > myfile имхо наиболее очевиден).
Куда ещё очевиднее/читабельнее?
Redirection of output causes the file whose name results from the expansion of word to be opened for
writing on file descriptor n, or the standard output (file descriptor 1) if n is not specified. If
the file does not exist it is created; if it does exist it is truncated to zero size.
Просто помните это и всё, никаких «чёрнодырных-кошечек».
И ещё, выделеный жирным кусок произойдёт до cat /dev/null, так что условно вы этой командой лишние ресурсы жрёте и файл дважды очищаете, потому как I/O Redirection башем парсится до исполнения команды которая что-то в редирект пишет.
Обычно есть либо coreutils, либо аналог (у BSD вроде свои coreutils), либо busybox, у которого cp — вполне себе встроен, хотя и не shell builtin (у меня busybox делает clone() и запускает cp в потомке). Я лично вездесущности /dev/null уверен меньше, чем в том, что там, где стоит интерактивная POSIX‐совместимая оболочка есть и cp.
Конечно же, бородатые гуру всегда укажут, где и что не так, но моё мнение об этом такое, что информации много не бывает. И особенно, когда изучаешь что-то неочевидное, никогда из одного источника ты ничему не научишься. Но прочитаешь 10 статей об одном и том же, но под другими ракурсами, и гораздо всё понятнее становится.
cat title.html > title.html
почему файл становится пустым?
Потому что для того, чтобы stdout был перенаправлен в title.html оболочке нужно сначала настроить stdout, а потом запустить exec, чтобы заменить себя на cat: cat не может настроить сам себе stdout, о > title.html
знает только оболочка, это не аргумент cat
. Т.к. в данном случае вы попросили обрезать выходной файл, то последовательность действий выглядит примерно так:
- Оболочка клонирует себя, создавай дочерний процесс.
- В дочернем процессе настраивается stdout: открывается файл title.html (сразу с обрезанием), закрывается старый stdout, открытый файл становится новым stdout.
- С настроенным stdout дочерний процесс, бывший клоном оболочки, заменяет себя на
cat
. cat
читает файл и выдаёт его в stdout, но файл‐то уже обрезан!
Точная последовательность и реализация зависит от оболочки, некоторые оболочки почему‐то даже предпочитают сохранить старый stdout куда‐то, заменить его на новый и только потом клонировать себя, после завершения же дочернего процесса закрыть новый stdout и вернуть старый на место. Если хотите посмотреть, как делает ваша оболочка, то запустите strace $SHELL -c 'cat title.html > title.html'
.
Но в любом случае, вы не сможете получить отличного поведения никаким образом, пока > title.html
не станет аргументом, который интерпретирует cat
(точнее, ваша замена cat
, потому как сам cat
такого не умеет): оболочка просто не может обрезать файл после чтения (которое ещё и будет выполняться кусками вперемешку с записью), а использование временных файлов или чего‐то в этом роде противоречит спецификации конструкции перенаправления вывода.
Bash-скрипты, часть 4: ввод и вывод