我的随机子目录中有一堆 MP4 文件。它们有我需要删除的随机前缀。此文件夹结构的示例是:
/
../AFolder/Afolder2/123-01-filename.mp4
../BFolder/Bfolder2/512-01-filname.mp4
../CFolder/Cfolder2/881-01-filename.mp4
基本上我想删除每个文件名前的 3 位数字以及破折号,因此最终文件变为:
/
../AFolder/Afolder2/01-filename.mp4
../BFolder/Bfolder2/01-filname.mp4
../CFolder/Cfolder2/01-filename.mp4
我尝试通过以下方式做到这一点:
for file in ./*/*/*mp4
do
changeto="(echo $name | cut -c4-)"
echo $name $changeto
#mv #name $changeto
done
但这会砍掉每个目录+文件的前 4 个,而不仅仅是最终文件。
答案1
按照您自己的使用 shell 循环的建议:
for name in ./*/*/???-*.mp4; do
filename=${name##*/} # remove directory path
filename=${filename#???-} # remove initial three characters and dash
# prepend directory path to target filename and rename
mv "$name" "${name%/*}/$filename"
done
这会循环我们想要更改的名称。对于每个路径名,filename
使用标准变量替换将路径名的文件名部分提取到变量中。从该值中,删除前三个字符和破折号。然后可以使用这个新值重命名原始文件$filename
。
如果您需要更严格地匹配文件名,确保前三个字符是数字,请将?
上面模式中的每个字符替换为[0-9]
或[[:digit:]]
。
使用 Perlrename
实用程序:
rename -v 's/...-([^\/]*\.mp4)$/$1/' ./*/*/???-*.mp4
这将对每个给定的文件名应用 Perl 替换。替换与文件名匹配,但仅捕获我们想要保留在末尾的名称位(最末尾的字符串不包含任何/
字符,前面是我们要删除的三个字符和一个破折号)。路径名的匹配部分将替换为捕获的字符串。
答案2
我喜欢用毫米波,对于这种事情。它允许您使用通配符 ?和 * 移动文件时。它将每个通配符视为正则表达式捕获组,这就是我的想法,但它使用 # 而不是 \ 来访问替换语法中的组。
这是这个问题的演示:
$ ls *Folder/*folder2/*
AFolder/Afolder2/123-01-filename.mp4 CFolder/Cfolder2/881-01-filename.mp4 BFolder/Bfolder2/512-01-filname.mp4
$ mmv "*Folder/*folder2/???-*" "#1Folder/#2folder2/#6"
$ ls *Folder/*folder2/*
AFolder/Afolder2/01-filename.mp4 CFolder/Cfolder2/01-filename.mp4 BFolder/Bfolder2/01-filname.mp4
棘手的地方是第一个字符串基本上必须始终用引号引起来,以避免从 shell 本身调用通配符。其次,记住每个?是它自己的组,这就是我们如何获得文件名其余部分的#6。
答案3
您可以使用查找并调用 shell-exec
find . -type f -exec sh -c '
for f; do
d=${f##*/} d=${d#*[0-9][0-9][0-9]-}
echo mv -v "$f" "${f%'/'*}/$d"
done
' _ {} +
- echo 是告诉你如何/执行什么,如果你认为 ouptu 没问题,请将其删除
实际输出是这样的。
输出
renamed './AFolder/Afolder2/123-01-filename.mp4' -> './AFolder/Afolder2/01-filename.mp4'
renamed './BFolder/Bfolder2/512-01-filename.mp4' -> './BFolder/Bfolder2/01-filename.mp4'
renamed './CFolder/Cfolder2/881-01-filename.mp4' -> './CFolder/Cfolder2/01-filename.mp4'