我有一些文件。我想从文件名中删除一些字符。这些字符可能在文件名的开头或结尾。不需要使用单个命令就可以将它们全部删除。
两个例子是:
从一个文件
01 - SongTitle.mp3
想剥离01 -
从另一个文件
SongTitle - ArtistName.mp3
想剥离- ArtistName
如果可能的话,我希望实现“要删除的字符串”和“要保留的字符串”类型,而不是这些示例特有的东西。我愿意命令要匹配的字符串并有“要删除的字符串”。
答案1
案例一
如果你想将文件重命名01 - This is a song.mp3
为This is a song.mp3
trimming01 -
开头。可以这样做,
$ echo "01 - This is a song.mp3" | sed 's/^[0-9]* - //'
This is a song.mp3
怎么运行的:
- 首先从这里的所有文件名中确定要替换的公共部分(文件名开头的两个数字,后跟一个空格、一个连字符和另一个空格)。
- 接下来我们需要一个针对公共部分的正则表达式。
- 插入符号
^
匹配字符串中第一个字符之前的位置,字符集[0-9]
匹配 0 到 9 之间的单个数字。 - 星号
^[0-9]*
匹配字符串开头的一个或多个 0 至 9 之间的数字。 - 我们所需的正则表达式也是如此
^[0-9]* -
,它匹配字符串开头的一个或多个 0 到 9 之间的数字,后跟一个空格、一个连字符和另一个空格。
从man sed
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successful,
replace that portion matched with replacement.
例如,在终端中尝试
$ echo "Good day" | sed 's/day/night/'
Good night
$ echo "Good day" | sed 's/day//' ## replacement is kept blank
Good
- 让我们回顾一下我们最初的问题。我们不希望匹配的部分保留在表达式中,而是使用 替换为空白
sed
。
案例二
您要重命名的第二组文件从This is a song - Some Artist.mp3
最后修剪。This is a song
尝试- Some Artist
$ echo "This is a song - Some Artist.mp3" | sed 's/ -.*/.mp3/'
This is a song.mp3
怎么运行的:
- 首先确定要替换的字符串。这里是字符串的一部分,从空格开始,后跟连字符,然后是字符串的其余部分。但我们希望扩展名
.mp3
保持完整。 - 这里我的方法是匹配空格后跟连字符的整个字符串,并将其替换为,
.mp3
以便替换后它仍然保留在字符串末尾的字符串中。 - 点
.
匹配单个字符,而不关心该字符是什么。唯一的例外是换行符。 -.*
匹配空格和连字符后的一个或多个任意字符。请注意,它也会匹配.mp3
。- 因此,
sed
我将匹配的部分替换为.mp3
您可以在正则表达式信息
针对案例 II 的更好的正则表达式
这部分内容摘自钢铁司机
echo "This is a song - Some Artist.mp3" | sed 's/ -[^.]*//'
This is a song.mp3
怎么运行的:
- 这里的方法是匹配字符串中空格后面、连字符后面、点前面
.
的部分.mp3
,并用空格替换匹配的部分。 [^.]
匹配除点之外的任意字符.
- 最后,正则表达式
-[^.]*
匹配一个空格,后跟一个连字符,一个或多个任意字符,但不匹配点.
,或者换句话说,在遇到点之前.
,这就是我们想要的正则表达式。
文件重命名
在 bash shell 中使用循环sed
重命名文件for
要按照案例 I 中所述重命名文件,您可以使用:
for i in *.mp3; do mv "$i" "$(echo $i | sed 's/^[0-9]* - //')" ; done
要按照案例 II 中所述重命名文件,您可以使用:
for i in *.mp3; do mv "$i" "$(echo $i | sed 's/ -.*/.mp3/')" ; done
避免使用 loop+sed 的更好方法rename
rename -v 's/^[0-9]* - //' *.mp3 # For the first set
rename -v 's/ -.*/.mp3/' *.mp3 # For the second set