从文件名中递归删除所有特殊字符

从文件名中递归删除所有特殊字符

我的目录和子目录中有多个文件包含 Microsoft 文件共享和 SharePoint 不支持的特殊字符。字符类型多种多样,从波浪号到与号再到谁知道什么。我使用过如下命令:

find . -type f -print | while read file
do
  file_clean=$( echo ${file} | tr " \~()&'" "_____" )
  mv $file $file_clean
done

并看到有人建议使用 globstar。但我仍然无法找到一个相对简单的命令来删除所有特殊字符,递归地只留下AZ,az,0-9(递归似乎是最难的部分)。

答案1

最简单的方法是桀骜。 Zsh 是基本 OS X 安装的一部分,但需要通过大多数 Linux 发行版上的包管理器进行安装,并从 *BSD 上的端口进行安装。 Zsh 提供了zmv功能使许多文件重命名任务变得容易。首先运行它(或将其放入您的.zshrc,以供交互使用):

autoload zmv

然后你可以使用

zmv '(**/)(*)' '$1${2//[^A-Za-z0-9]/_}'

或同等的

zmv '**/*' '$f:h${${f:t}//[^A-Za-z0-9]/_}'

第一个zmv命令将所有匹配的文件**/*(即当前目录和子目录中的所有文件递归地)重命名为同一目录 ( $1) 中的文件,并将基本名称转换为[^A-Za-z0-9]_.括号 导致(**/)(*)路径的目录部分(直到最后一个/)被分配给$1,文件的基本名称被分配给$2。第二个命令执行相同的操作,但使用$f引用整个原始名称和修饰语 :h:t提取名称的目录和基本部分。


您的脚本会以各种方式中断,因为它通过 shell 处理来运行各种特殊字符,而不是按字面意思处理它们。要了解原因,请阅读为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?

答案2

要获取所有文件名,您应该依赖空删除字符串:

find /your/path/ -print0 | while read -r -d $'\0' filename; do
    dn="`dirname "$filename"`"
    bn="`basename "$filename"`"
    bn_clean="`echo "$bn" | tr " \~()&'" "_______"`"
    file_clean="$dn/$bn_clean"
    if [ "$filename" != "$file_clean" ] ; then
        mv -fv "$filename" "$file_clean"
    fi
done

答案3

小心这一点:

perl -pi -e 's/\W//g' $(find . -type f)

您可以使用以下方法进行备份:

perl -pi.bak -e 's/\W//g' $(find . -type f)

相关内容