9

我正在编写一个 Bash 脚本来清理我的音乐。

我希望它格式化所有文件名并制作它们,所以通过一点互联网搜索,我写了这一行:

sed -i -e 's/[-_]/ /g' -e 's/ \+/ /g' -e **'s/\<[a-z]/\U&/g'** -e "s/$artist //g" -e "s/$album //g"

我曾经将文件名添加到文本文件然后 sed 它,但后来我不知道如何将新名称应用于文件。

于是我开始尝试重命名,并设法得到完全相同的结果,除了粗体部分,它应该使单词中的每个第一个字母大写。

rename 's/[-_]/ /g' * && rename 's/\s+/ /g' * && **rename 's/\s\w{1}/*A-Z*/g' *** && rename 's/^\d+[[:punct:]]\s//g' * && rename "s/$artist\s//g" * && rename "s/$album\s//g" * && rename "s/($ext)//g" *

现在, rename 中的代码正在工作(至少令人满意),在空格字符后只找到一个字母,但有问题的是替换。我尝试了许多不同的方法,结果都是在这种情况下,焦点的第一个字母被交换为 AZ。

在重命名手册页中,它说要使小写大写你做's/az/AZ/g',但很容易看出它只适用于它找到az AZ。所以这就是我需要帮助的。

如果有人知道如何像 sed 示例中那样做,那将是一个奖励,其中 \< 匹配每个单词的开头,因为目前,我的重命名命令不适用于第一个单词,也不会适用如果出于显而易见的原因有多个光盘看起来像“光盘名称 [光盘 1]”。

4

2 回答 2

15

这是一个 Perl 问题,因为rename它是用 Perl 编写的,如何执行重命名的说明是 Perl 命令。

为了s///让替换知道要插入哪个字母的大写版本,它必须从输入中“捕获”该字母。模式中的括号执行此操作,将捕获的字母存储在变量 中$1。并且\u在替换中使下一个字符大写。

所以你可以这样做:

$ rename 's/\s(\w)/ \u$1/g' *

请注意,替换部分必须在大写字母之前插入一个空格,因为该模式包含一个空格,因此空格和原始字母都将被替换。您可以通过使用 来避免这种\b情况,这是一个仅在单词边界匹配的零宽度断言:

$ rename 's/\b(\w)/\u$1/g' *

你也不需要{1}那里,因为\w(就像正则表达式中的其他符号一样)默认匹配单个字符。

最后,rename(1)中的示例实际上是y/A-Z/a-z/,使用y///运算符,而不是s///y///是一个完全不同的运算符,它将所有出现的一组字母替换为另一组;这对你没有用,它只是你想要大写的一些字符。

于 2013-01-09T16:52:04.243 回答
3
rename -nv 's{ (\A|\s) (\w+) }{$1\u$2}xmsg'

这将查找字符串的开头或后跟至少一个或多个单词字符(az、0-9、下划线)\A的空格。它将所有单词序列的第一个字符大写。\s\w+

于 2013-01-09T16:46:55.110 回答