find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh
我还没有尝试这里提到的更复杂的脚本,但是在我的Synology NAS上,没有一个单行命令版本适用于我。 rename
不可用,而且许多 find
的变体失败,因为它似乎坚持已重命名路径的旧名称(例如,如果它找到了 ./FOO
,然后是 ./FOO/BAR
,将 ./FOO
重命名为 ./foo
,即使该路径不再有效,它仍将继续列出 ./FOO/BAR
)。上面的命令对我来说没有任何问题。
以下是命令的每个部分的解释:
find . -depth -name '*[A-Z]*'
这将从当前目录中查找任何文件(将。
更改为您要处理的任何目录),使用深度优先搜索(例如,它将在列出./foo/bar
之前列出./foo
),但仅适用于包含大写字符的文件。 -name
过滤器仅适用于基本文件名,而不是完整路径。因此,这将列出./FOO/BAR
但不列出./FOO/bar
。这没问题,因为我们不想重命名./FOO/bar
。但我们确实想重命名./FOO
,但后者稍后列出(这就是为什么-depth
很重要)。
这个命令本身对于首先找到要重命名的文件特别有用。在完成重命名命令之后使用此命令来搜索由于文件名冲突或错误而尚未被替换的文件。
sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'
这部分读取由find
输出的文件,并使用正则表达式将它们格式化为mv
命令。 -n
选项阻止sed
打印输入,而搜索和替换正则表达式中的p
命令输出替换后的文本。
正则表达式本身由两个捕获组成:直到最后一个 / 的部分(即文件的目录)和文件名本身。目录保持不变,但文件名转换为小写。因此,如果
find
输出
./FOO/BAR
,它将变成
mv -n -v -T ./FOO/BAR ./FOO/bar
。
mv
的
-n
选项确保不会覆盖现有的小写文件。
-v
选项使
mv
输出它所做的每个更改(或未做的更改-如果
./FOO/bar
已经存在,则输出类似于
./FOO/BAR -> ./FOO/BAR
,指出没有进行任何更改)。这里非常重要的是
-T
- 它将目标文件视为目录。这将确保如果该目录存在,则不会将
./FOO/BAR
移动到
./FOO/bar
中。
与
find
结合使用,生成将执行的命令列表(方便验证实际执行之前的操作)。
sh
这个很容易理解。它将所有生成的
mv
命令路由到 shell 解释器。你可以用你喜欢的任何 shell 替换它,比如
bash
。
ABCdef
,abcDEF
和aBcDeF
),应该发生什么? 重命名脚本是否应该中止或只是警告并继续执行?2. 如何为非美国ASCII名称定义小写字母?如果可能存在这样的名称,是否应首先进行检查和排除操作?3. 如果您正在运行重命名操作 - Mihai Limbășan