识别文件名中包含非 ASCII 或不可打印字符的文件

sus*_*tus 28 shell bash character-encoding find filenames

在一个80GB大小的大约700,000个文件的目录中,有些文件名的文件名中含有非英文字符。除了费力地浏览文件列表之外,还有:

  • 列出或以其他方式识别这些文件名的简单方法?
  • 一种生成可打印的非英语字符的方法——那些未在可打印范围内列出的字符man ascii(以便我可以测试这些文件是否被识别)?

Lek*_*eyn 41

假设“foreign”表示“not an ASCII character”,那么您可以使用find模式来查找名称中没有可打印ASCII字符的所有文件:

LC_ALL=C find . -name '*[! -~]*'
Run Code Online (Sandbox Code Playgroud)

(空格是http://www.asciitable.com/ 上列出的第一个可打印字符,~是最后一个。)

提示 forLC_ALL=C是必需的(实际上LC_CTYPE=CLC_COLLATE=C),否则字符范围会被错误地解释。另请参阅手册页glob(7)。由于LC_ALL=C原因find将字符串解释为 ASCII,它会将多字节字符(例如?)打印为问号。要解决此问题,请通过管道连接到某个程序(例如cat)或重定向到文件。

除了指定字符范围外,[:print:]还可用于选择“可打印字符”。一定要设置 C 语言环境,否则你会得到相当(看似)任意的行为。

例子:

$ touch $(printf '\u03c0') "$(printf 'x\ty')"
$ ls -F
dir/  foo  foo.c  xrestop-0.4/  xrestop-0.4.tar.gz  ?
$ find -name '*[! -~]*'       # this is broken (LC_COLLATE=en_US.UTF-8)
./x?y
./dir
./?
... (a lot more)
./foo.c
$ LC_ALL=C find . -name '*[! -~]*'
./x?y
./??
$ LC_ALL=C find . -name '*[! -~]*' | cat
./x y
./?
$ LC_ALL=C find . -name '*[![:print:]]*' | cat
./x y
./?
Run Code Online (Sandbox Code Playgroud)


Tim*_*imo 6

如果使用翻译每个文件名tr -d '[\200-\377]'并将其与原始名称进行比较,则任何具有特殊字符的文件名都将不同。

(以上假设您的意思是非 ASCII 与外国)

  • 这也删除了大多数 `tr` 实现中的 `[` 和 `]`。 (2认同)