获取文件和目录列表:
要递归地操作文件,find
与 glob 相比, using 是更好的解决方案。我建议在开始操作之前使用文件名填充 bash 数组。此外,我认为一次执行此步骤,目录然后文件,将是谨慎的。您不想重命名目录,然后在重命名文件时发现该文件不存在。出于同样的原因,该脚本在文件系统层次结构上逐渐更深的级别上工作也很重要(因此在sort
下面使用)。
在列表上操作:
获得列表后,您可以调用一个通用的 shell 函数来执行文件或目录名称的规范化和重命名。请注意正确引用名称以获得所需内容的重要性。这是非常重要的,因为 bash(或任何外壳程序)在解析命令行时使用空格作为单词边界。
剧本:
以下脚本(./rename_spaces.bash
在下面的示例输出中命名)应该执行您想要的操作。要添加您自己的怪异字符,请将它们添加到weirdchars
变量中。请注意,您需要根据需要对字符进行转义(例如,单引号已被转义)。如果新文件名存在,脚本会跳过一条消息。这也意味着它将打印用于琐碎重命名的消息(原始名称中没有奇怪字符的文件名)。这对某些人来说可能很烦人(例如我:-p)
#!/bin/bash
# set -o xtrace # uncomment for debugging
declare weirdchars=" &\'"
function normalise_and_rename() {
declare -a list=("${!1}")
for fileordir in "${list[@]}";
do
newname="${fileordir//[${weirdchars}]/_}"
[[ ! -a "$newname" ]] && \
mv "$fileordir" "$newname" || \
echo "Skipping existing file, $newname."
done
}
declare -a dirs files
while IFS= read -r -d '' dir; do
dirs+=("$dir")
done < <(find -type d -print0 | sort -z)
normalise_and_rename dirs[@]
while IFS= read -r -d '' file; do
files+=("$file")
done < <(find -type f -print0 | sort -z)
normalise_and_rename files[@]
这是一个带有目录树的示例输出,其中目录和文件在运行上述脚本之前和之后的名称中有空格。
$ tree
.
├── dir1
│ ├── subdir1\ with\ spaces
│ │ └── file1
│ └── subdir2\ with\ spaces&weird\ chars'
│ └── file2
├── dir2
│ ├── subdir1\ with\ spaces
│ │ └── file1\ with\ space
│ └── subdir2\ with\ spaces
│ └── file2\ with\ space
├── dir3
│ ├── subdir1
│ │ └── file1
│ ├── subdir2
│ │ └── file2
│ └── subdir3
│ └── file3
└── rename_spaces.bash
10 directories, 8 files
$ ./rename_spaces.bash
$ tree
.
├── dir1
│ ├── subdir1_with_spaces
│ │ └── file1
│ └── subdir2_with_spaces_weird_chars_
│ └── file2
├── dir2
│ ├── subdir1_with_spaces
│ │ └── file1_with_space
│ └── subdir2_with_spaces
│ └── file2_with_space
├── dir3
│ ├── subdir1
│ │ └── file1
│ ├── subdir2
│ │ └── file2
│ └── subdir3
│ └── file3
└── rename_spaces.bash
10 directories, 8 files
注意:实现脚本以对任何非字母数字的内容“做正确的事”似乎并非易事。例如,我不确定如何处理文件或目录名称中的点或预先存在的下划线或其他“常规”允许的字符。
以通用方式识别不良/特殊字符也是一个问题。在国际语言环境中,情况更加复杂。我不知道任何简单的说法允许“只允许英文字母中的数字或字符”。如果有人有想法,请继续并发布答案。