查找并删除具有非 ASCII 名称的文件
通过使用ls命令和grep命令的组合,可以找到和删除非ASCII名称的文件。下面是具体的解决方法:
首先,使用ls命令来列出当前目录下的所有文件,并将每个文件的inode号添加到前缀。命令如下:
ls -1 -R -i
接下来,使用grep命令进行过滤,只保留包含指定字符列表之外字符的行。由于输入可能包含二进制字符,所以需要使用-a选项将输入视为文本。命令如下:
grep -a "[^A-Za-z0-9_.':@ /-]"
最后,使用while循环遍历每一行,提取出inode号,并将其传递给find命令进行文件删除。命令如下:
while read f do inode=$(echo "$f" | cut -d ' ' -f 1) find -inum "$inode" -delete done
这样,就可以找到并删除非ASCII名称的文件。希望对大家有所帮助。
在使用find命令查找和删除文件时,可能会遇到文件名包含非ASCII字符的问题。这种情况下,常规的find命令可能无法正常工作,因为默认情况下,find命令使用的语言环境不支持非ASCII字符。
为了解决这个问题,可以通过设置LC_ALL环境变量为C来修改find命令的语言环境。具体的解决方法如下:
LC_ALL=C find . -regex '.*[^ -~].*' -print # -delete
或者:
LC_ALL=C find . -type f -regex '*[^[:alnum:][:punct:]]*' -print # -delete
这两个命令可以通过设置LC_ALL环境变量为C来查找和删除文件名中包含非ASCII字符的文件。其中,第一个命令使用正则表达式'.*[^ -~].*'来匹配包含非ASCII字符的文件名,第二个命令使用正则表达式'*[^[:alnum:][:punct:]]*'来匹配包含非ASCII字符的文件名。在执行这两个命令之前,需要先将打印出来的文件名正确无误后,再移除命令中的#字符,以实际删除文件。
如果想要了解更多关于如何在grep中查找所有非ASCII字符的信息,可以参考这个链接:How do I grep for all non-ASCII characters。
非ASCII字符是指ASCII字符代码大于0x7F的字符。这包括大部分UTF-8字符,因为ASCII字符实际上是UTF-8的一个子集。如果删除包含非ASCII字符的文件,可能会误删其他语言命名的合法文件。
ASCII控制字符是指ASCII字符代码在0x00到0x1F和0x7F之间的控制字符,比如ESC(0x1B)。在默认情况下,ls命令将所有控制字符显示为问号,除非使用--show-control-chars选项。猜测你想要删除的文件包含ASCII控制字符,而不是非ASCII字符。
POSIX提供了一系列处理这些字符的字符类。其中,[:cntrl:]表示控制字符,[:graph:]表示可打印的图形字符(不包括空格字符),[:print:]表示可打印字符(包括空格字符)。
Perl兼容正则表达式(PCRE)允许使用十六进制字符代码,语法为\x00。PCRE还提供了[:ascii:]字符类,是[\x00-\x7F]的简写。GNU的grep支持PCRE(使用-P选项),但BSD的grep不支持。GNU和BSD的find命令都不支持PCRE正则表达式。
要查找文件名中包含非打印控制字符的文件,可以使用GNU的find命令,使用POSIX正则表达式,命令如下:
find -type f -regextype posix-basic -regex '^.*/[^/]*[[:cntrl:]][^/]*$'
要删除匹配的文件,只需在find命令中添加-delete选项:
find -type f -regextype posix-basic -regex '^.*/[^/]*[[:cntrl:]][^/]*$' -delete
强烈建议在使用-delete选项之前先运行不带-delete的命令,以便查看将被删除的内容。
如果还想查看正在删除的内容,可以添加-print选项:
find -type f -regextype posix-basic -regex '^.*/[^/]*[[:cntrl:]][^/]*$' -print -delete
如果要删除包含控制字符的路径(文件或目录),可以简化正则表达式,并且不需要-type选项:
find -regextype posix-basic -regex '.*[[:cntrl:]].*' -print -delete
更新:查找非ASCII和控制字符
如果文件名既包含非ASCII字符又包含ASCII控制字符,则可以使用PCRE正则表达式。通过使用find命令遍历目录树,并将结果传递给Perl进行处理。
为了处理可能包含换行符的文件名,需要在find命令中使用-print0选项,并在Perl代码中添加-0标志来指定记录之间的分隔符。以下命令将递归打印当前目录中的所有路径:
find . -print0 | perl -n0e 'print $_, "\n"'
以下是匹配包含非ASCII或非打印(即控制)字符的名称的PCRE正则表达式:
[[:^ascii:][:cntrl:]]
以下命令将打印当前目录中与该正则表达式匹配的所有路径(包括目录和文件):
find . -print0 | perl -n0e 'chomp; print $_, "\n" if /[[:^ascii:][:cntrl:]]/'
要删除匹配的文件和目录,可以使用以下命令:
find . -print0 | perl -MFile::Path=remove_tree -n0e 'chomp; remove_tree($_, {verbose=>1}) if /[[:^ascii:][:cntrl:]]/'
此命令还会打印删除的内容,但控制字符会被解释,因此输出与ls命令的输出不完全匹配。
此外,还可以使用[:print:]或[:graph:]字符类进行匹配。