我正在尝试替换一堆* .txt文件中的字符串。我熟悉这个命令:
find "$folder" -type f -name '*.txt' -exec sed -i 's/REPLACEFROM/REPLACETO/g' {} \;
但是,这个(根据-i标志)替换了现场的字符串。
我想做的是保持所有原始文件不变,并将更改的文件“保存”为“file1-renamed.txt”,“file2-renamed.txt”,...
最快,最优雅的方式是什么?也许perl?
我确信这是非常基本的,但对我来说似乎很难。 :)
提前感谢您的帮助。
答案 0 :(得分:3)
使用sed,您可以使用
sed -i.back
这样,原始文件将被移动到* .back
或者使用此代码段与您的问题最接近:
find "$folder" -type f -name '*.txt' -exec bash -c '
cp "$1" "${1%.*}-renamed.txt"
sed -i 's/REPLACEFROM/REPLACETO/g' "${1%.*}-renamed.txt"
' -- {} \;
答案 1 :(得分:2)
使用perl你可以尝试这样的事情:
find "$folder" -name '*.txt' |
xargs perl -ne 'open NEW, ">>$ARGV.new"; s/from/to/g; print NEW'
这会将新文件保存为old-name.txt.new。如果您真的需要“old-name-renamed.txt”格式,则可能需要更改它。另请注意,每次执行oneliner后它都会附加到新文件中。
当然,使用-i选项(... perl -i.old -pe 's/from/to/g'
)然后将文件批量重命名为所需的名称格式会更容易,因此只有原始文件无法进行写入时,此解决方案才有意义。
答案 2 :(得分:0)
这不是一个单行,但它应该诀窍(和IMO它更容易阅读):
use strict;
use warnings;
while(@ARGV)
{
my $file=shift;
open(my $read,"<",$file) or die $!;
my $output_file=$file . "_renamed";
if($file=~/^(.+)\.txt$/)
{
$output_file=$1 . "-renamed.txt";
}
open(my $write,">",$output_file) or die $!;
while(<$read>)
{
chomp;
s/REPLACEFROM/REPLACETO/g;
print $write "$_\n";
}
close($read);
close($write);
}
答案 3 :(得分:0)
这可能对您有用:
find "$folder" -type f -name '*.txt' |
parallel sed 's/REPLACEFROM/REPLACETO/g' ">" {.}-renamed.txt
答案 4 :(得分:0)
我已经在这里发布了answer,但今天我想到了另一个解决方案:
for f in (find "$folder" -name '*.txt'); do perl -ne 's/from/to/g' $f > "$f.new"; done
同样,它会将修改后的内容保存到“old-name.txt.new”(如果需要,可以将其更改为... > "$(basename $f)-renamed.txt" ...
。)
这个答案比我之前的答案更好,因为它不需要为每个新行打开相同的文件。