我有一个 38GB 的文件夹,里面有 800 个 MP4 视频。重新下载后,文件名变成了无间距,所有单词都连接起来,但仍然是 TitleCase。
所以从TitleCase
我需要Title Case
。
批量重命名这些文件的最有效方法是什么?
我记得很久以前我的发行版中就包含了rename
或,但现在似乎没有了。autorename
答案1
如果要在 mp4 文件名 TitleCase 的每个“单词”之间添加空格(PascalCase 到以空格分隔的单词):
rename -n 's/\B[[:upper:]]/ $&/g' ./*.mp4
输出
rename(./FooBarBaz.mp4, ./Foo Bar Baz.mp4)
查看这篇文章,其中深入详细介绍了 Perlrename
答案2
我不知道什么是最有效的方法(我认为你的意思是有效),但我会快速编写一个 for 循环,例如:
for file in *.mp4; do
newname="$(echo "$file" | sed 's/\(.\)\([A-Z]\)/\1 \2/g')"
mv "${file}" "${newname}"
done
解释:
newname="$(echo "$file" | sed 's/\(.\)\([A-Z]\)/\1 \2/g')"
# ^-------------------- Assign to variable "newname" value…
# ^------------------- "$()": as output by commannd in parentheses;
# use "" to avoid word splitting
在哪里
echo $file | sed 's/\(.\)\([A-Z]\)/\1 \2/g'
# ^-------------------------------------- output old file name
# ^-------------------------------- pipe to `sed` command
sed
是“流编辑器”的名称;它接受输入,对其执行命令,并产生输出。这里的命令是s
,如“搜索和替换”中所示。
s/\(.\)\([A-Z]\)/\1 \2/g
^^ ^ ^ ^ ^ ^ ^ ^
|| |^ | | ^^^ | | | |
\------------------------ s: search and replace
\----------------------- /: Set the search;replace;flags separator to "/"
|| | | \|/ | \ / |
\--+------------------ \(…\): a "capture group" (the first one);
| | | | || | whatever is matches the content will be
| | | | \| | available as \1
\-------------------- .: We match ".", which means *any* character
| | | | | (which precludes this from matching at start of line)
\------+--------- \(…\): Second capture group, \2
\------------- [A-Z]: Match any capital letter
| |
\----- Replacement: "\1 \2" replace
| "characterbeforecapitalletter""Capitalletter" with
| "characterbeforecapitalletter" "Capitalletter"
|
\- g: Flag that means "global": Repeat this until
end of line
答案3
要分隔标题大小写中的单词,例如 to FooBarBaz.mp4
be Foo Bar Baz.mp4
,您可以在每个大写字母之前插入一个空格,除非它是文件名中的第一个字符,使用 zshzmv
可以(递归地)执行以下操作:
$ autoload -Uz zmv
$ zmv -n '(**/)(?)(*.mp4)' '$1$2${3//(#m)[[:upper:]]/ $MATCH}'
mv -- FooBarBaz.mp4 'Foo Bar Baz.mp4'
mv -- OnceUponATime.mp4 'Once Upon A Time.mp4'
(-n
如果愿意,请删除以进行空运行)。
当心它会Foo-Bar.mp4
变成Foo- Bar.mp4
.
zmv -n '(**/)(*.mp4)' '$1${2//(#b)([[:alpha:]])([[:upper:]])/$match[1] $match[2]}'
只会在字母和大写字母之间插入空格,但不适用于OnceUponATime
上面,因为空格将插入到n
and之间A
,而不是插入到A
和之间,T
因为A
已经是消耗的通过之前的替换。
由于 zsh glob 没有与 perl 的环视操作符相当的功能,因此解决这个问题更加困难。在这种情况下,一个简单的方法是额外重复一次替换:
$ zmv -n '(**/)(*.mp4)' '$1${${2//(#b)([[:alpha:]])([[:upper:]])/$match[1] $match[2]}//(#b)([[:alpha:]])([[:upper:]])/$match[1] $match[2]}'
mv -- ABCDEF.mp4 'A B C D E F.mp4'
mv -- AChristmasCarol.mp4 'A Christmas Carol.mp4'
mv -- FooBarBaz.mp4 'Foo Bar Baz.mp4'
mv -- LeSongeD\'UneNuitD\'Été.mp4 'Le Songe D'\''Une Nuit D'\'Été.mp4
mv -- LifeOfΠ.mp4 'Life Of Π.mp4'
mv -- OnceUponATime.mp4 'Once Upon A Time.mp4'
答案4
其他答案描述了允许基于正则表达式进行更改的工具,这是一个很好的方法。然而,这些答案并没有解决一个重要的问题(恕我直言):在磁盘上实际进行更改之前预览功能(这可能很难逆转)。
输入 Emacs 及其dired
模式,特别是wdired
,记录在手动的。可以打开包含文件的目录的 dired,切换 wdired 以使文件名可编辑,进行更改 - 最有可能使用交互式正则表达式搜索和替换,查看更改,最后将它们提交到磁盘。
我知道为这个用例安装 Emacs 是一种严厉的方法,但我要指出的是,它可以轻松地处理带有困难字符(例如空格)的文件名。