我有这个脚本,它只处理父文件夹,不重命名子文件夹和文件-我希望它能去掉所有带_的非数字。
#!/bin/bash
for f in *
do
new="${f// /_}"
if [ "$new" != "$f" ]
then
if [ -e "$new" ]
then
echo not renaming ""$f"" because ""$new"" already exists
else
echo moving "$f" to "$new"
mv "$f" "$new"
fi
fi
done
获取文件和目录列表:
要递归地操作文件,与globs相比,使用find
是更好的解决方案。我建议您在开始操作文件名之前,先用文件名填充bash数组。此外,我认为一步一个脚印,目录然后文件,这样做是谨慎的。您不想重命名目录,然后在重命名文件时发现该文件不存在。同样重要的是,出于同样的原因,脚本在文件系统层次结构上的更深层次上工作(因此使用了下面的sort
)。
在列表上操作:
一旦你有了列表,你就可以调用一个通用的shell函数来进行文件或目录名的规范化和重命名。请注意正确引用姓名以获得所需信息的重要性。这一点非常重要,因为bash(或任何shell)在解析命令行时使用空格作为单词边界。
脚本:
下面的脚本(在下面的示例输出中命名为./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
注意:实现脚本来为任何非字母数字的内容"做正确的事情"似乎并不简单。例如,我不知道如何处理文件或目录名中的句点、预先存在的下划线或其他"常规"允许的字符。
以通用的方式识别不需要的/特殊的字符也是一个问题。在国际语言环境中,它更为复杂。我不知道有什么简单的说法可以"只允许英文字母表中的数字或字符"。如果有人有想法,请发表答案。
您也可以尝试递归运行该命令(可能有一种方法可以在不调用相同脚本的情况下完成此操作,但我现在无法使其工作):
假设此脚本在您的路径中或此处/usr/local/bin/remove_spaces.sh
:
#!/bin/bash
for f in *
do
if [ -d "$f" ]
then
cd "$f"
/usr/local/bin/remove_spaces.sh
cd ..
fi
new="${f// /_}"
if [ "$new" != "$f" ]
then
if [ -e "$new" ]
then
echo not renaming ""$f"" because ""$new"" already exists
else
echo moving "$f" to "$new"
mv "$f" "$new"
fi
fi
done
因此,您基本上应该检查当前文件f
是否是一个目录,如果是,cd到它并重新运行该命令,然后cd退出并在需要时进行重命名。
在bash的最新版本中,您可以使用
for f in **
您可能需要设置globstar选项才能使其工作:
shopt -s globstar
如果文件名不能包含制表符或换行符(注意引号):
IFS="$(printf 'nt')"
for file in $(find .) ; do
COMMAND "$file" ...
done
另请参阅Shell 中的文件名和路径名
find | {
read f
while [ -n "$f" ]
do
# process "$f" (always with the quotes)
read f
done
}