![用于查找和删除文件名中的子字符串的 Bash shell 脚本](https://linux22.com/image/17438/%E7%94%A8%E4%BA%8E%E6%9F%A5%E6%89%BE%E5%92%8C%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6%E5%90%8D%E4%B8%AD%E7%9A%84%E5%AD%90%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%20Bash%20shell%20%E8%84%9A%E6%9C%AC.png)
我正在尝试在 Mac OS X 10.6 中编写一个 bash shell 脚本(由 Automator Action 调用)来重命名多年来我命名不当的电视节目 DVD rip。我想删除文件名中的部分文本。我想删除出现在我知道将始终出现在文件名中的特定字符系列之后的文本。但我不知道在已知的一系列字符之前或之后会出现多少个字符。我也不知道之前或之后的文本是否包含多个句点或破折号。一个例子可能会有所帮助:
大爆炸理论.S01E01.xxxxxxxxxxx.mp4
我知道每个文件始终包含 SxxExx 格式的字符串,其中 x 始终是数字。但我不知道数字会是多少。我想要获取文件名,包括 SxxExx 字符串和文件扩展名,但删除其他所有内容。所以对于上面的例子我最终会得到:
生活大爆炸S01E01.mp4
我尝试过使用 bash 的内置字符串替换命令。我认为 expr index 命令会给我 SxxExx 字符串的起点,然后我可以使用 ${filename:offset:length} 只提取文件名所需的部分(我已经知道扩展名,以便可以重新提取)添加)。但 OS X 版本的 expr 似乎不包含索引功能。我之前只用过 Basic 和 LotusScript 编写过脚本。在这些环境中,使用“Like”、“Instr”或“Mid”等命令相当容易。但在 bash 中我就是无法弄清楚。我花了几个小时在谷歌上搜索试图了解如何使用正则表达式来定位文件名中的“SxxExx”子字符串,但我就是无法弄清楚。我希望一些聪明的 UNIX 脚本编写者能够帮助我!
答案1
尝试这个:
newname=`echo "$filename" | sed -e 's/\(S[0-9][0-9]E[0-9][0-9]\).*\.mp4/\1.mp4/'`
正则表达式为:
- 开始一个小组 ( \( )
- 匹配 SXXXEXX,其中 X 是 0 到 9 之间的数字
- 端基 (\))
- 匹配任意数量的任意字符(换行符除外)
- 匹配显式字符串 ( .mp4 )
在替换表达式中:
- 替换为第一组中匹配的字符串 ( \1 )
- 替换为显式字符串 ( .mp4 )
答案2
假设您有一个文件名列表以及file-list
文件中的路径,请尝试以下操作
while IFS= read -r path; do
newpath=$(printf '%s\n' "$path" |
sed 's/\(.*S[0-9]*E[0-9]*\.\).*\.\([^.]*\)$/\1\2/')
echo mv -- "$path" "$newpath"
done <file-list
使用的正则表达式的含义sed
以及与示例输入的比较"The.Big.Bang.Theory.S01E01.xxxxxxxxxxx.mp4"
\( start of group 1
.* The.Big.Bang.Theory. any sequence of characters
S[0-9]* S01 a capital S followed by 0 or more digits
E[0-9]* E01 a capital E followed by 0 or more digits
\. . a dot
\) end of group 1
.* xxxxxxxxxxx any sequence of characters
\. . a dot
\( start of group 2
[^.]* mp4 a sequence of 0 or more non-dot characters
\) end of group 2
$ end of line
在输出中,字符串的\1\2
意思是“输出 group1 后跟 group2 (因此要删除xxxxxxxxxxx.
)
如果满意则删除echo
。