我需要在 CentOS 7 机器上递归重命名数千个文件,当前格式为:
(32-64 alphanumerics)_various special characters.wav
简而言之,我想递归地从所有 3 层深度的文件中删除扩展_
名(注意:所有扩展名都是).wav
.wav
示例: 现有:
/home/user/recordings/TEST/december/157A757989F047C3AC2EC3499B4D04A5_7075276189 by [email protected] @ 8_44_52 AM.wav
/home/user/recordings/test/october/28D1E1840DE24D9DB4CF6D1A707533F6337C2DDE_2018690759 by [email protected] @ 1_26_55 PM.wav
期望:
/home/user/recordings/TEST/december/157A757989F047C3AC2EC3499B4D04A5.wav
/home/user/recordings/test/october/28D1E1840DE24D9DB4CF6D1A707533F6337C2DDE.wav
我进行了大量搜索,发现了很多修改文件名其他部分的方法,但没有保留特定字符 ( _
) 和扩展名之前的所有内容。
预先感谢您的任何帮助。
答案1
您必须提取目录部分、文件名以及前面的字符第一的下划线(因为所有文件都.wav
没有必要将扩展名保存在单独的变量中):
find /home/scott/ -maxdepth 4 -type f -name '*_*.wav' -exec sh -c 'h=${1%/*}
t=${1##*/}; echo mv "$1" "${h}/${t%%_*}".wav' doom {} \;
删除echo
以实际重命名文件。
答案2
我进行了大量搜索,发现了很多修改文件名其他部分的方法,但没有保留特定字符 (_) 和扩展名之前的所有内容。
这sed
似乎可以解决问题:
sed -E 's/(.*)_[0-9].* by .*(\.wav)/\1\2/'
echo "/home/user/recordings/TEST/december/157A757989F047C3AC2EC3499B4D04A5_7075276189 by [email protected] @ 8_44_52 AM.wav" | sed -E 's/(.*)_[0-9].* by .*(\.wav)/\1\2/'
/home/user/recordings/TEST/december/157A757989F047C3AC2EC3499B4D04A5.wav
对其他示例字符串进行测试:
echo "/home/user/recordings/test/october/28D1E1840DE24D9DB4CF6D1A707533F6337C2DDE_2018690759 by [email protected] @ 1_26_55 PM.wav" | sed -E 's/(.*)_[0-9].* by .*(\.wav)/\1\2/'
/home/user/recordings/test/october/28D1E1840DE24D9DB4CF6D1A707533F6337C2DDE.wav
使用时sed
,您可以保存部分表情()
,然后将它们放回原处\1\2
。
答案3
prename
例如,安装任何(Perl 重命名)实现File::Rename
或来自Unicode::Tussle
。 (最后我看到,CentOS 没有任何 Perl 重命名,只有 util-linuxrename
不能满足您的需要,但这可能在 CentOS 7 中发生了变化。)它们都有基本语法,其中有一些用于转换每个文件名的 Perl 代码。prename CODE FILENAME...
CODE
find /home/user/recordings/ -type f -exec prename 's!_[^/]*(\.[^./]*)$!$1!' {} +
Perl的解释:(\.[^./]*)$
匹配名称末尾的扩展名;_[^/]*
匹配文件名中的所有内容,不包含从第一个下划线开始的目录部分(无斜杠)。替换为$
,即第一个且唯一的括号组中的部分。