文件名中无法识别的字符(linux)

文件名中无法识别的字符(linux)

我在 Linux Mint 中访问文件时遇到问题。原因显然是文件名中存在无法识别的字符,但我所知道的所有技术都无法帮助我重命名它。

因此,详细信息如下:文件名类似于:

êà_0_4àíòè_0_7-_0_7_0_8ó_0_1à333333.mp3

或者至少这是我的文件管理器和终端显示的方式。

我无法使用在 Linux Mint、媒体播放器等下使用的任何程序打开该文件……

无法通过文件管理器重命名、移动或复制。所有这些操作都会产生类似以下的错误消息:

(重命名):

Error renaming file: No such file or directory.

(用于复制/移动):

No such file or directory.

我也尝试过使用通配符从终端重命名命令。该命令正确地选择了文件名,但无法复制,以下是输出:

cp *0_7-_* 1.mp3
cp: cannot open `êà_0_4àíòè_0_7-_0_7_0_8ó_0_1à333333.mp3' for reading: No such file or directory

我也尝试过使用 mv 命令,

mv *0_7-_* 1.mp3
mv: cannot move `êà_0_4àíòè_0_7-_0_7_0_8ó_0_1à333333.mp3' to `1.mp3': No such file or directory

如果我尝试sudo 重命名然后我得到:

Unrecognized character \xC3; marked by <-- HERE after <-- HERE near column 1 at (eval 1) line 1.

文件本身是有效的MP3文件。可以在XP下使用Windows Media Player打开。

问题是:我有一个很大的音乐库(超过 100GB),并且有少量类似的文件名称中包含无效字符。我不想丢失这些文件,我想弄清楚将来如何处理这种情况(最好在 Linux 中,因为我没有运行 Windows 的 PC)。

任何帮助将不胜感激

更新: 根据 terdon 的要求,结果如下locale

LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

更新2 我刚刚检查了我朋友的 XP 机器。我可以确认以下发现。原始文件可以通过 Windows Media Player 播放,但不能通过 Winamp 播放。但是,通过文件管理器访问并重命名后,两个播放器都可以播放它。

所以我得出结论无法识别字符的问题。不过,我仍然对 Linux 下的解决方案感兴趣,

答案1

四件事:

尝试解决方案的补充 - 移动其他所有内容,然后删除所有内容。

mkdir ../everything_else
mv problematic/folder/path/* everything_else
sudo rm -rf problematic/folder/path

确保文件上没有 ACL,并删除任何可能导致问题的 ACL:

$ /bin/ls -le problematic/folder/path
total 16
-rw-r--r--+ 1 whmcclos  staff  1918 Dec 18 09:00 README
0: user:_spotlight inherited allow read,execute,readattr,readextattr,readsecurity
$ chmod -a "..."

尝试使用 Perl 脚本来消除 OS/FS 命名依赖关系?

例如,与此代码片段类似的内容 - 将文件名保存在匿名 $_ 中:

$ mkdir fred; cd fred; touch a b c d e f
$ cat > try.pl
#!/usr/bin/perl
opendir(D,".") or die "cannot open .\n";
@files=readdir(D);
closedir(D);
foreach (@files) {
  next if /\.{1,2}/;                      # Skip directory entries
  print; print "? "; $r = <>; chop($r);   # Provide some level of control
  if($r eq "y" or $r eq "Y") {unlink;}    # Should report if cannot unlink unnamed file - tbd.
}
^D
$ /usr/bin/perl try.pl
a? 
b? 
c? y
d? 
e? 
f? 
$ ls
a       b       d       e       f       try.pl

[已更新以反映作者的初衷 - 将野兽复制到表现良好的文件(名称):]

为了查看 Perl 是否可以将行为不当的文件复制到行为良好的文件,我将使用下面的 Perl 脚本 - 仍然遵循上面的思路 - 让 Perl“匿名”访问文件名。

(此外,确实应该检查 ACL;从我记得处理的情况来看,ACL 甚至可以阻止 root 以 root 身份正常访问文件。)

以下是 Perl 脚本:

$ cat try3.pl
#!/usr/bin/perl
# A code fragment to ask to copy a displayed file to $TO; chg $TO on next line:
$TO="my_new_behaved_filename";       # This is the name that will be copied to
opendir(D,".") or die "cannot open .\n";
@files=readdir(D);
closedir(D);
foreach $f (@files) {
  next if $f =~ /\.{1,2}/;           # Skip directory entries, "." & ".."
  print "$f? "; $r = <>; chop($r);   # Provide some level of control; "y" or "Y"
  if($r eq "y" or $r eq "Y") {       #   to copy the displayed filename to $TO
    print "copying it to $TO...\n";
    # Now, see if we can copy the darn thing to $TO:
    open(FROM,$f) or die "sorry - couldn't open it...";
    open(TO,">$TO");
    while(read FROM, $buf, 16384) {
      print TO $buf;
    }
    close(TO);
    close(FROM);
  }
}

假设 try3.pl 是前面提到的 Perl 脚本,您就可以使用它:

$ ./try3.pl 
a? 
b? 
d? y
copying it to my_new_behaved_filename...
e? 
f? 

通过符号或硬链接访问文件并查看您获得的里程。

我将使用 vi 的文件名 [tab] 扩展来尝试向 shell “识别”您想要链接到的文件。

我将 ~/{.vim,.viminfo,.vimrc} 移到一边,以便限制 wildmenu 输入等内容。您可能也想这样做。

现在,在虚假文件的包含文件夹中启动以下命令行序列:

$ vi

在 vi 中,准确输入以下字符序列

!!ln -s [tab]

因此,该按键顺序用文字表示为:感叹号、感叹号、el、en、空白、破折号、es、空白、tab。只要按下 [tab] 键,当前工作目录中的第一个文件应该显示在 vi 状态行的空白字符(在“s”后面)后面。多次按下 [tab] 键可循环显示虚假文件名。当虚假文件名出现时,按空格键添加空格,然后输入新文件/链接名称。

vi 状态行上的结果应如下所示

!!ln -s bogus_filename new_sym_link_name

按下回车键来查看链接命令(由 vi 生成,用于替换 vi 空缓冲区中的当前空行,这里我们不关心这个空行;我们想要执行带有制表符扩展的 shell 命令的副作用)是否会创建链接 new_sym_link_name。

使用 :q![return] 退出 vi,看看是否可以通过符号链接访问您的文件。

(您也可以通过省略上面 ln 命令中的 -s 来尝试硬链接。

因为我刚刚注意到您可以通过 Windows 更改文件名,所以我想回车换行序列不知何故进入了文件名,这会混淆各种方法。

答案2

用于ls -li获取相关文件的 inode 编号。记下 inode 编号(第一个字段)。我将使用它123456作为示例。

然后,使用find删除文件:

find -inum 123456 -exec rm {} \;

或者重命名:

find -inum 123456 -exec mv {} some_better_filename \;

相关内容