如果要同时重命名文件和目录,将会遇到一些问题。重命名一个文件很容易。但是您要确保目录也被重命名。您不能简单地说,mv Motörhead/Encöding Motorhead/Encoding
因为Motorhead
在通话时将不存在。
因此,我们需要对所有文件和文件夹进行深度优先遍历,然后仅重命名当前文件或文件夹。以下find
在我的OS X上使用GNU 和Bash 4.2.42。
#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
d="$( dirname "$file" )"
f="$( basename "$file" )"
new="${f//[^a-zA-Z0-9\/\._\-]/}"
if [ "$f" != "$new" ] # if equal, name is already clean, so leave alone
then
if [ -e "$d/$new" ]
then
echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
ls -ld "$d/$new" "$d/$f"
else
echo mv "$file" "$d/$new" # remove "echo" to actually rename things
fi
fi
done
new="${f//[\\\/\:\*\?\"<>|]/}"
如果要替换Windows无法处理的任何内容,可以使用来更改正则表达式。
将该脚本另存为rename.sh
,使其可使用来执行chmod +x rename.sh
。然后,将其命名为rename.sh /some/path
。
确保解决所有文件名冲突(“ Notice
”公告)。
如果您完全确定它可以进行正确的替换,请echo
从脚本中删除,以实际重命名内容,而不仅仅是打印其内容。
为了安全起见,建议您先对一小部分文件进行测试。
选项说明
要解释发生了什么:
-depth
将确保目录从深度优先递归,因此我们可以从头开始“汇总”所有内容。通常,find
遍历的方式有所不同(但不是广度优先)。
-print0
确保find
输出为null分隔,所以我们可以用它读read -d ''
入file
变量。这样做有助于我们处理各种奇怪的文件名,包括带空格的文件名,甚至包括换行符。
- 我们将使用获取文件目录
dirname
。不要忘记总是正确引用变量,否则任何带有空格或通配符的路径都会破坏此脚本。
- 我们将使用获取实际的文件名(或目录名)
basename
。
- 然后,我们从
$f
使用Bash的字符串替换功能中删除所有无效字符。无效是指不是小写或大写字母,数字,斜杠(\/
),点(\.
),下划线或减号的任何内容。
- 如果
$f
已经清除(清除的名称与当前名称相同),请跳过它。
- 如果
$new
目录中已经存在$d
(例如,您的文件名为,resume
并且résumé
在同一目录中),请发出警告。您不想重命名,因为在某些系统上mv foo foo
会引起问题。除此以外,
- 最后,我们将原始文件(或目录)重命名为其新名称。
由于这只会作用于最深的层次结构,因此重命名Motörhead/Encöding
到Motorhead/Encoding
两个步骤:
mv Motörhead/Encöding Motörhead/Encoding
mv Motörhead Motorhead
这样可以确保所有替换均以正确的顺序进行。
示例文件和测试运行
让我们假设一个基本文件夹中的一些文件test
:
test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule
下面是从一个运行的输出在调试模式(与echo
在前面mv
),即,将被称为命令,并碰撞警告:
mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r-- … … test/work/resume
-rw-r—r-- … … test/work/résumé
注意对于不存在的消息with-hyphen.txt
,schedule
和test
本身。
mv
已经存在的目标的情况,这种情况可能发生(1)如果您的文件已经清理干净(导致mv foo foo
),或者(2)如果您的文件具有相同的名称,除了用于特殊字符(例如,,除之外mv Encöding Encoding
,您还已有Encoding
文件Encöding
)。