上面写着perlrun
请注意,由于-i 在创建同名新文件之前会重命名或删除原始文件,因此不会保留 Unix 样式的软链接和硬链接。
所以-i 无法做到这一点。
这是 Perl 的另一种方式(标记为 -- 即使有一个干净的解决方案,sed)
我使用文件a.txt、b.txt、它们的符号链接(ln -s a.txt ln_a.txt 等)和c.txt(任何内容都可以用于此测试),并在文件中列出链接名称和c.txt
ln_a.txt ln_b.txt c.txt # 文件“input_list.txt”
input_list.txt 中的文件/链接名称可以用空格或换行符分隔。
然后,在每个输入文件的第一行打开一个临时输出文件,并将每个已处理的行写入其中。一旦到达输入文件的末尾,将该临时输出重命名为其输入文件,或者如果它是一个链接,则重命名为它的目标。因此,对于每个输入文件,使用输出文件覆盖文件或其目标(如果链接)。
cat input_list.txt | xargs perl -MPath::Tiny -ne'
if ($.==1) { $tf = $ARGV."_tmp.$$"; $fh = path($tf)->openw };
s/(\w+)/$1-NEW/;
print $fh $_;
if (eof) { close ARGV; rename $tf, (-l $ARGV ? readlink $ARGV : $ARGV) }
'
这会更改目标的内容并单独保留链接。它也适用于常规文件。
临时输出文件名 (filename_tmp.$$) 可以使用 File::Temp 正确生成,或者更确切地说是使用 Path::Tiny::tempfile,因为该模块已被使用。
为了可移植性,rename 可能应该从 File::Copy 更改为 move。
使用的eof 检查每个输入文件的文件是否已用尽,此时输出文件被重命名为输入文件或其目标。 -l 是一个file-test operator,用于测试手头文件是否为符号链接,如果是,则readlink 解析链接。
此时rename输入文件或目标是安全的,因为它已被读取和处理。
$ARGV 是名称
当前处理的文件,ARGV 是它的文件句柄。
显式close ARGV 重置行计数器,因此我们可以通过测试行号计数器$. 与1 来打开每个新输入文件开头的临时输出。