Как игнорировать файлы только для чтения с помощью `perl -i`?
Переключатель Perls -i
появляется, чтобы изменить файлы только для чтения:
$ echo 'foobar' > tmp.txt
$ chmod -w tmp.txt
$ perl -pi -w -e 's/foobar/FOOBAR/' tmp.txt
$ cat tmp.txt
FOOBAR
Это неожиданно, так как команда не должна была изменять файл на свои разрешения. Ожидается, что попытка обновления с помощью других средств завершится неудачно:
$ echo 'barbaz' > tmp.txt
-bash: tmp.txt: Permission denied
Почему Perl модифицирует файлы только для чтения (и как?) и, что самое главное, как я могу заставить Perl не делать этого?
Единственный информативный ресурс, который я могу найти в этом разделе, находится в часто задаваемых вопросах Perl:
Разрешения на файл говорят, что может случиться с данными в этом файле.... Если вы попытаетесь записать в файл, разрешения файла определяют, разрешено ли вам.
В конечном итоге кажется, что он говорит, что он не должен писать на него, поскольку файловая система говорит, что вы не можете.
Ответы
Ответ 1
Фильтр @ARGV
в блоке BEGIN
:
perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV} s/foobar/FOOBAR/' files
Теперь, если ни один из файлов в командной строке не доступен для записи, @ARGV
будет пустым, а дескриптор файла ARGV
попытается прочитать из STDIN
. Я могу думать о двух способах избежать этого:
-
Закройте STDIN
в блоке BEGIN
тоже
perl -pi -e 'BEGIN{close STDIN;@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files
-
Всегда вызывайте этот однострочный перенаправляющий ввод из /dev/null
perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files < /dev/null
Ответ 2
Смотрите документацию в perlrun:
переименование входного файла, открытие выходного файла по имени оригинала и выбор этого выходного файла в качестве параметров по умолчанию для операторов print()
(...)
Для обсуждения вопросов, связанных с разрешениями файлов и -i, см. "Почему Perl позволяет мне удалить файлы только для чтения? Почему -i clobber защищает файлы? Разве это не ошибка в Perl?" В perlfaq5.
Ответ 3
Из perlrun:
-i
указывает, что файлы, обработанные конструкцией < > , редактируются на месте. Он делает это, переименовывая входной файл, открывая выходной файл по исходному имени и выбирая этот выходной файл как значение по умолчанию для операторов print().
Таким образом, он действительно не изменяет файл. Он перемещает файл в сторону (для этого требуются права на запись в записи, а не права на запись файла), а затем создает новый со старым именем.
как я могу заставить Perl не делать этого?
Я не думаю, что вы можете использовать -i
.