Мой друг указывает, что если вы делаете:
perl -pi.bak -e 's/foo/bar/' somefile
когда «somefile» на самом деле является символической ссылкой, perl делает то, что говорят документы:
Это делается путем переименования входного файла, открытия выходного файла с исходным именем и выбора этого выходного файла в качестве операторов по умолчанию для print (). Расширение, если оно указано, используется для изменения имени старого файла, чтобы сделать резервную копию [...]
В результате получается новая символическая ссылка "somefile.bak", указывающая на неизмененный реальный файл, и новый, измененный обычный файл "somefile" с изменениями.
Во многих случаях следование символической ссылке было бы желательным поведением (даже если оно оставляет правильное расположение файла .bak неоднозначным). Есть ли простой способ сделать это, кроме проверки символических ссылок в оболочке и надлежащего обращения с регистром?
( sed
делает то же самое, для чего это стоит.)
-p -i
в вашем сценарии.Ответы:
Интересно, поможет ли в этом случае небольшая
sponge
универсальная утилита («впитать стандартный ввод и записать в файл») из moreutils и будет ли она следовать символической ссылке.Автор описывает
sponge
так:источник
sponge
такое использование? Что касается меня: пока нет. Не могли бы вы оставить комментарий о том, что он вел себя в тесте так, как хотелось бы здесь? О, я вижу комментарий. Спасибо за подтверждение!file
в приведенном выше примере есть символическая ссылка, ссылка остается одна, и реальный файл изменился.Если вы знаете, что
somefile
это символическая ссылка, вы можете явно указать полный путь к файлу с помощью следующего:perl -pi.bak -e 's/foo/bar/' $(readlink somefile)
Таким образом, исходная символическая ссылка остается неизменной, поскольку замена теперь выполняется непосредственно с исходным файлом.
источник
readlink
может быть еще одна символическая ссылка. Лучше всего было бы использовать-f
или-e
где доступны илиzsh
«s$file:P
или(:P)
шарик Классификатор , как показано на @ikegami , чтобы получить символическую ссылку свободного пробега.Если вы имеете дело с одним файлом, команда будет выглядеть следующим образом:
Решение тогда следующее:
Это обрабатывает как символические, так и не символические ссылки.
Если вы имеете дело с произвольно большим количеством файлов, команда будет выглядеть следующим образом:
Решение тогда следующее:
Это обрабатывает как символические, так и не символические ссылки.
Caveat
readlink
- это не стандартная команда, поэтому ее присутствие, аргументы и функциональность зависят от системы, поэтому обязательно ознакомьтесь с документацией. Например, некоторые реализации имеют-f
(что вы также можете использовать здесь), но нет-e
, некоторые тоже .busybox
«Sreadlink -f
ведет себя как GNUreadlink -e
. И у некоторых систем естьrealpath
команда, вместоreadlink
которой обычно ведет себя как GNUreadlink -f
.Помните, что в GNU
readlink -e
символические ссылки, которые не могут быть разрешены в существующий файл, удаляются без уведомления.источник
$var:P
у меня не работает. (X='tmp' zsh -c 'perl -E"say for @ARGV" $X:P'
выходыtmp:P
)$var:P
. С более старыми версиями вы всегда можете использовать$var:A
вместо этого. См. Руководство по различиям и zsh.org/mla/users/2016/msg00593.html для обоснования введения:P
(настоящийrealpath()
интерфейс).:A
был добавлен в 4.3.10 (2009), GNUreadlink -z
в 2012, я не знаю ни одной другойreadlink
реализации, которая поддерживает-z
). Обратите внимание, что с GNUxargs
вы обычно хотите эту-r
опцию, если не можете гарантировать, что ввод не будет пустым. Здесь нет ничего сложного (еслиperl
код не содержит оператораBEGIN
/END
), вы просто получите-i used with no filenames on the command line, reading from STDIN.
предупреждение, если это произойдет.-r
документацию. Я думал, что сделал противоположное тому, что он делает. Readded.