是否有像mv这样的linux命令,但带有正则表达式?


Answers:


32

正如其他人提到的那样,rename它擅长于此,但是man rename在尝试之前请阅读手册页()。至少有两种完全不同的工具可以调用,rename而哪种工具取决于您的发行版。错误地呼叫它们可能很危险。

这是 Ubuntu随附的Larry Wall的基于Perl版本的手册页。您给它一个perl表达式,例如rename 's/\.sql$/.php/' *.sql

这是旧版Red Hat和CentOS发行版附带的重命名的手册页。用法是简单的字符串替换,例如rename .sql .php *.sql

您还可以使用bash单行处理一次处理每个文件:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done

有人可以为基于Perl的重命名上传Windows二进制文件吗?
mcandre

Perl版本重命名无法将文件从一个文件系统移动到另一个文件系统。
lilydjwg

bash一线是有帮助的,尤其是在没有rename功能时(例如,busybox)
artm

10

rename(1),它不使用正则表达式,但可以解决您的问题:

rename .sql .php *.sql

也有mmv(1),但我不熟悉它的工作方式。


在Ubuntu和Debian(不确定其他发行版)中,默认情况下/usr/bin/rename链接到正/usr/bin/prename则表达式。
ℝaphink

5

G'day,

您也可以尝试输入

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

或者使用正则表达式将其略微更改为

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

以获得一些shell编码的乐趣。(-:


2
对于名称中包含空格的文件,此操作将失败,因此请小心。每个人都应该永远解析ls输出
slhck

sed例子是相当不错的,虽然。
明亮的星星

2

作为水管工,我喜欢管道:)

注意:这个答案是冗长的-作为一个新手,我很感谢认识的人花时间解释,所以我付出了“前进”的代价。如果您不是新手,请原谅您的篇幅和冗长。

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

哪里:

ls -1 *_201[67][0-9]*

列出与该模式匹配的所有文件,在这种情况下,我正在寻找文件名中日期为'YYYYMMDD'的文件

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1:第一个捕获组-整个文件名

^ 2:第二个捕获组-文件名模式的第一部分

^ 3:第三个捕获组-第二个文件名部分-在此处,日期为'YYYYMMDD'

^ 4:第四个捕获组-日期和扩展名之间以及扩展名本身之间的可选文件名部分

Sooooo ....如果我有一个名为

CallLog_555123412_20161231-214403.7z

...然后

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

实际上意味着

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

注意,sed命令的输出通过管道传递到“ bash”以执行它。为了首先看到建议的文件移动而没有实际移动它们,请首先删除'| bash”,然后像这样尝试:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

这根本不会做任何更改,但是如果您使用'|运行它,您将看到将执行的命令。bash”标记在最后。

这很有用,因为您可以从文件名中的各个部分创建所需的任何子目录,也可以在sed命令的“替换”文本中添加任何其他内容。注意,sed需要很多转义字符。

SED Regex括号:

(...)需要转义以进行捕获分组-> \(... \)

{m,n}需要转义以量化先前的对象-> \ {m,n \}

/要求转义替换字符串-> \ /

[...]不需要转义字符类

替换字符串中的\ 1表示捕获的第一个组,依此类推...

安全警告:除非您完全了解结果,否则切勿用任何方式“抨击” ...

希望可以帮助清除一些障碍:)


1

安装mmv,然后执行以下操作:

mmv "*.sql" "#1.php"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.