我认为以下内容可以在一次通过中完成您想要的一切.
# Update: if this doesn't work, use read -d '' instead
find . -print0 | while IFS= read -d '$\000' f ;
do
orig_f="$f"
# Below is pure bash. You can replace with tr if you like
# f="$( echo $f | tr -d ,\' | tr "$'&'@- " "ya__" )"
f="${f// /_}" # Replace spaces with _
f="${f//\'}" # Remove single quote
f="${f//-/_}" # Replace - with _
f="${f//,}" # Remove commas
f="${f//&/y}" # Replace ampersand with y
f="${f//@/a}" # Replace at sign with a
f=$( iconv -f UTF8 -t ASCII//TRANSLIT <<< "$f" )
new_dir="$(dirname $f)"
new_f="$(basename $f)"
mkdir -p "$new_dir"
mv -i "$orig_f" "$new_dir/$new_f"
done
find命令(不需要实际选项,除了-print0来处理带空格的文件名)将向while循环发送空分隔文件名(毫无疑问,有人会在那里纠正我的错误).利用参数扩展的一长串分配删除/替换各种字符;我将使用tr作为注释的等效管道包含在内.然后我们通过iconv运行文件名来处理字符集问题.最后,我们将名称拆分为其路径和文件名组件,因为我们可能必须在执行mv之前创建一个新目录.