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


47

我的档案中含有这类无效的字元

009_-_�%86ndringshåndtering.html

这是Æ文件名出错的地方。

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

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

echo "009_-_�%86ndringshåndtering.html" | tr ???

5
字符可能不是“无效”,否则文件系统不会储存它们(除非你做了一件真正讨厌的FS)。您是否尝试过更改语言环境(例如更改为UTF8)以正确显示名称?
James O'Gorman 2012年

Answers:


41

一种方法是使用sed:

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

file当然,用您的文件名替换。这将用下划线替换不是字母,数字,句点,下划线或破折号的任何内容。您可以添加或删除字符以使其保持不变,和/或将替换字符更改为其他任何字符,或完全不进行任何更改。


4
我曾经用过:f='file'; mv 'file' ${f//[^A-Za-z0-9._-]/_}
路易(Louis)

1
在下面寻找H. Hess的最佳解决方案...(以及我的有趣评论:))
Jan Sila

31

我假设您在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 .

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

sudo apt-get install convmv

每次都能为我工作,并且确实会恢复原始文件名。

资料来源:LeaseWebLabs


1
这看起来很有希望,但是有什么主意如何知道编码是什么?我Save the current file in Word 97-2004 format\sco.workflow在Mac上(通过Microsoft Office)创建了一个名为的目录,上述编码没有任何效果。
Sridhar Sarnobat '16

值得指出的是,默认情况下,convmv在“测试”模式下运行,在该模式下,它仅执行空运行并告诉您它将移动哪些文件。然后它将告诉您再次运行它,并带有--notest实际重命名文件的选项。
肯尼·拉沙特

16

我以为您是说要遍历文件系统并修复所有此类文件?

这是我会做的方式

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

这将查找所有带有非ASCII字符的文件,并用下划线(_)替换这些字符。但是请谨慎使用,如果已经存在一个使用新名称的文件,它将被覆盖。可以修改脚本来检查这种情况,但我并没有为了简化起见而输入。


13

遵循https://stackoverflow.com/questions/2124010/grep-regex-to-match-non-ascii-characters的答案,您可以使用:

rename 's/[^\x00-\x7F]//g' *

这里*要重命名文件相匹配。如果要在多个目录中执行此操作,则可以执行以下操作:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

您可以使用-n参数进行rename空运行,并查看要更改的内容,而无需更改。


有没有办法修改它以保留诸如ü和ä这样的外来字符?
年长者怪胎

只有第二个为我工作。一切都在同一个目录中,所以我不确定有什么区别。
Shautieh

1
@Shautieh:-n阻止它实际运行。我会澄清答案。
naught101 '03

处理大量文件时,重命名可能会很慢。如果您想加快速度,请将支票推入查找。我不知道该怎么做。
isaaclw

13

我从损坏的USB记忆棒中恢复了一些日语文件,但文件名损坏,上述解决方案对我不起作用。

我推荐排毒包:

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

用法示例:

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

2
这应该更高,我敦促每个人detox在本质上重新发明轮子之前先看看。如果查看手册页,由于其灵活性,它会覆盖此处所有其他建议的解决方案。
emk2203 '18

以西结书25:17-以慈善和善良的名义投票支持这种解决办法的人是有福的,因为他确实是他兄弟的守护者和寻找失散孩子的人。
Jan Sila

直觉上,路径不能为“。”。在Debian中。如果使用“。” 它什么也没找到。
isaaclw

我不知道它是否真的有效,似乎删除/替换了中文字符,例如的节奏啊,但是这些字符是有效的文件名。
林果皞

5

此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'

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

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


1
它是我搜索的!但添加引号以支持带空格的目录查找“ $ 1” -depth -exec bash -c'清除“ $ 0”'{} \;
mmv-ru


0

我使用这种单行代码来删除字幕文件中的无效字符:

for f in *.srt; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.]/./g' |sed 's/\.\.\././g' |sed 's/\.\././g'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done
  1. 仅处理* .srt文件(*可以代替* .srt来处理每个文件)
  2. 除去字母A-Za-z,数字0-9和句点“”之外的所有其他字符。
  3. 删除可能的两次或三次
  4. 检查文件名是否包含无效字符
  5. 如果为true,它将使用mv命令重命名该文件,然后输出使用echo命令进行的更改。

-2

用于*中的文件;做mv“ $ file” $(回显“ $ file” | sed -e's / [^ A-Za-z0-9。- ] / / g'); 完成&


2
您应该解释代码的作用并使用正确的格式。您的代码可以通过在名称中引入冲突来导致文件被删除。在后台运行整个过程有点愚蠢。
kasperd
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.