Bash oneliner重命名文件名

时间:2014-12-25 22:43:13

标签: linux bash perl file-rename

我经常想轻易地重命名一堆文件。我总是不得不与findgrepxargssed一起努力完成工作。我想了解如何使用PCRE做得更好

这是我的档案:

$ find .
.
./08447.ctags
./10565.gitignore
./38037.inputrc
./42257.bashrc
./51395.gitk
./63705.gitconfig
./66352.octave_hist
./67049.ahk
./85869.vimrc
./89518.minttyrc
./desktop.ini
./dp4FontViewer64.exe
./SBZSwitcher_v1.8.9.7z
./xlive.rar

我会正确地重命名点文件,因为我可以使用这个oneliner:

$ find . | grep -e '^[.]\/[0-9]\+[.]' | sed -r 's/^.*[.](\w+)$/\0 .\1/' | xargs -n2 mv

但是我发现这个命令非常复杂,我正在寻找一些我可以轻松使用的东西:

$ rename 's/^\.\/\d+\.(\w+)$/\1/' .

我的另一种解决方案是编写这个Perl脚本:

#!/usr/bin/env perl
use 5.010;
use File::Find;

die "Wrong regexp!" unless
    $ARGV[0] =~ m/^
        s(?<delimiter>\/|~|@|;|%|`|\|)
        (?<search>.*)
        (?&delimiter)
        (?<replace>.*)
        (?&delimiter)
        (?<flags>.*)$/x;

my $search = join('', map("(?$_)", split('', $+{flags}))).$+{search};
my $replace = '"'.$+{replace}.'"';
find(sub { rename($_, s/$search/$replace/ree) }, $ARGV[1]);

有没有更好的解决方案?

1 个答案:

答案 0 :(得分:3)

这是一个简单的解决方案。

如果你的rename命令没问题,但你希望它是递归的,那么:

shopt -s globstar
rename 's/^\.\/\d+\.(\w+)$/\1/' **

find -type f -exec rename 's/^\.\/\d+\.(\w+)$/\1/' {} +

warning http://pix.toile-libre.org/upload/original/1377510865.png 还有其他同名工具可能会或可能不会这样做,所以要小心。

如果您运行以下命令(linux

$ file $(readlink -f $(type -p rename))

你有一个像

的结果
.../rename: Perl script, ASCII text executable

且不包含ELF

然后这似乎是正确的工具=)

如果没有,请将其设为Debian上的默认值(通常已经是这种情况)和Ubuntu之类的衍生物:

$ sudo update-alternatives --set rename /path/to/rename

(将/path/to/rename替换为perl's rename命令的路径。


如果您没有此命令,请搜索您的软件包管理器进行安装或do it manually


最后但同样重要的是,这个工具最初是由Perl的父亲Larry Wall编写的。