Почему я должен указывать ключ -i с расширением резервной копии при использовании ActivePerl?

Я не могу заставить однострочники Perl для редактирования на месте, работающие под ActivePerl, работать, если я не укажу их с расширением резервного копирования:

C:\> perl -i -ape "splice (@F, 2, 0, q(inserted text)); $_ = qq(@F\n);" file1.txt
Can't do inplace edit without backup.

Та же команда с -i.bak или -i.orig работает хорошо, но в процессе создает нежелательный файл резервной копии.

Есть ли способ обойти это?


person Zaid    schedule 11.04.2010    source источник


Ответы (2)


Это ограничение Windows/MS-DOS. Согласно perldiag:

Вы находитесь в такой системе, как MS-DOS, которая запутается, если вы попытаетесь прочитать из удаленного (но все еще открытого) файла. Вы должны сказать -i.bak или что-то в этом роде.

Реализация Perl -i заставляет его удалить file1.txt, сохраняя при этом открытый дескриптор, а затем заново создать файл с тем же именем. Это позволяет вам «читать» файл file1.txt, даже если он был удален и создается заново. К сожалению, Windows/MS-DOS не позволяет удалить файл, к которому прикреплен открытый дескриптор, поэтому этот механизм не работает.

Лучше всего использовать -i.bak, а затем удалить файл резервной копии. Это, по крайней мере, дает вам некоторую защиту — например, вы можете не удалять резервную копию, если perl завершает работу с ненулевым кодом выхода. Что-то типа:

perl -i.bak -ape "splice...." file1.txt && del file1.bak
person rjh    schedule 11.04.2010
comment
Так что это ограничение Windows. Я надеялся, что мне не придется unlink создавать резервную копию отдельной командой... похоже, придется. Спасибо за помощь. - person Zaid; 11.04.2010
comment
Не совсем связано, но мне кажется, что редактирование на месте в sed в Windows работает. Я вижу, что ваш пример не будет работать в sed, но это может быть полезно знать. - person Mike; 10.04.2014
comment
@Mike: С моей стороны, sed редактирование на месте оставляет временные файлы, например, sedGihEwg в файловой системе - у вас нет? Какая у вас версия? Я использую GNU sed version 4.2.1. - person zb226; 07.10.2016
comment
@Zaid IMO, это реализация Perl, а не ограничение Windows. Если вы переносите программу на другую ОС, ваш перенос должен учитывать особенности этой ОС, и Perl в этом случае, похоже, не беспокоит. - person antred; 12.02.2018
comment
И под какашками я подразумеваю бедных. Извиняюсь. - person antred; 12.02.2018

Пример с рекурсивным изменением и удалением, выполненным с помощью find. Работает, например. mingw git bash на окнах.

$ find . -name "*.xml" -print0 | xargs -0 perl -p -i.bak -e 's#\s*<property name="blah" value="false" />\s*##g'
$ find . -name "*.bak" -print0 | xargs -0 rm

Двоичные завершающие значения, передаваемые между find/xargs для обработки пробелов. Необычный префикс s/, чтобы избежать искажения xml в поисковом запросе. Это предполагает, что у вас не было .bak файлов для начала.

person shuckc    schedule 11.11.2014