如何从文件名中删除无效字符?

San*_*dra 69 linux bash

我有这样的无效字符的文件

009_-_?%86ndringshåndtering.html
Run Code Online (Sandbox Code Playgroud)

这是Æ文件名出现问题的地方。

有没有办法只删除所有无效字符?

或者可以tr以某种方式使用?

echo "009_-_?%86ndringshåndtering.html" | tr ???
Run Code Online (Sandbox Code Playgroud)

Jam*_*ger 55

一种方法是使用 sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')
Run Code Online (Sandbox Code Playgroud)

file当然,替换为您的文件名。这将用下划线替换不是字母、数字、句点、下划线或破折号的任何内容。您可以根据需要添加或删除字符以保留,和/或将替换字符更改为任何其他字符,或根本不更改。

  • 我用过:`f='file'; mv '文件' ${f//[^A-Za-z0-9._-]/_}` (5认同)
  • 这_会_在重音字符上严重失败。除了ascii 之外还有其他任何东西。绝对_不是_原始问题的解决方案。 (3认同)
  • 在下面寻找 H. Hess 的最佳解决方案......(以及我旁边的有趣评论:)) (2认同)

小智 52

我从损坏的 U 盘中恢复了一些文件名损坏的日文文件,上述解决方案对我不起作用。

我推荐排毒套餐:

detox 实用程序重命名文件以使其更易于使用。它消除了空间和其他类似的烦恼。它还将翻译或清除以 8 位 ASCII 编码的 Latin-1 (ISO 8859-1) 字符、以 UTF-8 编码的 Unicode 字符和 CGI​​ 转义字符。

用法示例:

detox -r -v /path/to/your/files
Run Code Online (Sandbox Code Playgroud)
-r 递归到子目录
-v 详细说明正在重命名的文件 
-n 可用于试运行(仅显示将要更改的内容)

  • 这应该高得多,我敦促大家在重新发明轮子之前先看看“排毒”。如果您查看手册页,您会发现它涵盖了此处提出的所有其他解决方案,因为它具有灵活性。 (6认同)
  • 以西结书 25:17 - 以慈善和善意的名义支持此解决方案的人是有福的,因为他确实是他兄弟的守护者和失散儿童的发现者。 (4认同)
  • 不直观地,路径不能是 '.' 在 Debian 中。如果您使用“.” 它什么也没找到。 (4认同)
  • 小心使用这个工具。这非常具有侵略性。它甚至将空格更改为下划线:/还将`__init__.py`重命名为init_.py (3认同)
  • 我想知道它是否真的有效,似乎删除/替换了中文字符,例如`的节奏啊`,但这些字符是有效的文件名。 (2认同)
  • 使用绝对路径!/home/you/some - 相对的“。” 不适用于它,否则很棒的工具!:) (2认同)

小智 43

我假设您使用的是 Linux 机器并且文件是在 Windows 机器上制作的。Linux 使用 UTF-8 作为文件名的字符编码,而 Windows 使用其他编码。我认为这是问题的原因。

我会使用“convmv”。这是一种可以将文件名从一种字符编码转换为另一种字符编码的工具。对于西欧,其中一种通常有效:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .
Run Code Online (Sandbox Code Playgroud)

如果您需要在基于 Debian 的 Linux 上安装它,您可以通过运行:

sudo apt-get install convmv
Run Code Online (Sandbox Code Playgroud)

它每次都对我有用,并且确实恢复了原始文件名。

资料来源:LeaseWebLabs

  • 值得指出的是,默认情况下,convmv 在“测试”模式下运行,它只是执行试运行并告诉您它将移动哪些文件。然后它会告诉你使用`--notes`选项再次运行它以实际重命名文件。 (2认同)

phe*_*mer 20

我假设您的意思是要遍历文件系统并修复所有此类文件?

这是我要做的方式

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'
Run Code Online (Sandbox Code Playgroud)

这将找到所有具有非 ascii 字符的文件,并用下划线 ( _)替换这些字符。但是要小心,如果具有新名称的文件已经存在,它将覆盖它。可以修改脚本来检查这种情况,但为了简单起见,我没有把它放进去。


nau*_*101 16

以下/sf/ask/148680731/ 的答案,您可以使用:

rename 's/[^\x00-\x7F]//g' *
Run Code Online (Sandbox Code Playgroud)

where*匹配您要重命名的文件。如果要在多个目录上执行此操作,可以执行以下操作:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;
Run Code Online (Sandbox Code Playgroud)

您可以使用 -n 参数进行rename试运行,看看会发生什么变化,而无需更改它。


Kri*_*Dev 6

这个 shell 脚本递归地清理目录,使文件在 Linux/Windows 和 FAT/NTFS/exFAT 之间可移植。它删除控制字符/:*?"<>\|和一些保留的 Windows 名称,如COM0.

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'
Run Code Online (Sandbox Code Playgroud)

Linux 理论上限制较少(/并且\0在文件名中严格禁止),但实际上有几个字符会干扰 bash 命令(例如*...),因此在文件名中也应避免使用它们。

文件命名限制的重要来源: