Bash脚本替换文件中所有出现的字符串,包括文件名

时间:2014-04-10 14:32:26

标签: regex perl bash unix sh

我希望能够将目录中所有文件的文件内容和文件名中的一个字符串替换为另一个字符串减去" .git"目录。我有以下代码,这对于更改文件名有好处,但不能替换文件中的字符串。我做错了什么?

#!/bin/bash

# Replace occurances in files, lowercase
lower1=$(echo $1 | tr '[:upper:]' '[:lower:]')
lower2=$(echo $2 | tr '[:upper:]' '[:lower:]')
echo "Replacing $lower1 with $lower2..."
find . -type f \! -iregex '.\|./.git' -exec perl -i -pe 's/$lower1/$lower2/g' {} \;

# Replace all other occurances in files to capitalised
upper2=$(echo ${2:0:1} | tr '[:lower:]' '[:upper:]')${2:1}
echo "Replacing all $1 with $upper2..."
find . -type f \! -iregex '.\|./.git' -exec perl -i -pe 's/$1/$upper2/gi' {} \;

# Replace filenames. Use "bash -c" to pass files as arguments to mv command.
# This worked
find . -name "*$lower1*" -exec bash -c 'mv "$1" "${1/$2/$3}"' -- {} $lower1 $lower2 \;

我确实尝试过sed,但这并不允许不区分大小写。

我在OSX Mountain Lion上测试这个,如果这有所不同,尽管我也希望这也适用于Linux。我此刻离开了我的Linux机器。

3 个答案:

答案 0 :(得分:2)

只需使用File::Find

即可

以下代码将编辑整个目录树,因此我会小心使用它。也许先进行一些测试? :)

此脚本接受两个字符串作为参数,然后用$ string2替换$ string1的所有出现。对于完美的小写匹配,它将替换为小写的$ string2,但对于所有其他匹配,它将替换为大写的$ string2。

目前,它只会为文件重命名做小写。

use strict;
use warnings;
use autodie;

use File::Find;

die "Usage: $0 From_string To_string\n" if @ARGV != 2;

my ($from, $to) = map lc, @ARGV;

finddepth(sub {
    return if $File::Find::dir =~ /.git\b/;

    # Inplace Edit of files
    if (-f) {
        local @ARGV = $_;
        local $^I = '.bak';
        while (<>) {
            s/\Q$from/$to/g;
            s/\Q$from/\U$to/ig;
            print; 
        }
        #unlink "$_$^I";  # Uncomment if you want to delete backups
    }

    # Rename File
    my $newfile = $_;
    if ($newfile =~ s/\Q$from/$to/ig) {
        rename $_, $newfile;
    }
}, '.');

答案 1 :(得分:0)

find . -name .git -prune -o type f -exec perl -i -pe "s/\Q$1\E/\L$2\E/i" {} +
find . -name .git -prune -o type f -name "*$lower1*" -exec mmv "*$lower1*" "#1$lower2#2" {} +

如果您正在进行大量文件重命名,则应检查是否意外删除了中间结果。 mmv表现令人钦佩。

+find提升了性能。

答案 2 :(得分:0)

这是我设法提出的解决方案。感谢所有帮助我的人:

#!/bin/bash

# Replace occurances in files, lowercase
lower1=$(echo $1 | tr '[:upper:]' '[:lower:]')
lower2=$(echo $2 | tr '[:upper:]' '[:lower:]')
echo "Replacing $lower1 with $lower2..."
find . -type f \! -iregex '.\|./.git' -exec perl -i'' -pe "s/$lower1/$lower2/g" {} +

# Replace all other occurances in files to capitalised
upper2=$(echo ${2:0:1} | tr '[:lower:]' '[:upper:]')${2:1}
echo "Replacing all $1 with $upper2..."
find . -type f \! -iregex '.\|./.git' -exec perl -i'' -pe "s/$1/$upper2/gi" {} +

# Replace filenames.
mmv -r ";*$lower1*" "#2$lower2#3"