无法删除/移动文件名中带有特殊字符的文件

无法删除/移动文件名中带有特殊字符的文件

正如您在下面看到的,这些文件包含不常见的字符。

文件管理器截图

在终端或 Dolphin 中删除它们都会返回错误:

没有这样的文件或目录

ls -la在目录上运行后我得到了以下输出:

-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ?2?.???љ?!?Gb??σ?[?F?
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 3l??#g?w????O?JKB7?co??քH??bT?NA???S???X?I?A?qC??M?I???
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??8??-?@,?Zp?[?bI????7^?ñ[?ڏ??z?O???ч??eEȰ?+??,OF??h

fsck从另一个操作系统对该分区运行了一个命令,但没有任何改变。

我该如何删除这些文件?

答案1

一个简单的方法是通过它们的 inode 删除这些文件。:)

ls -li在包含不常见字符的目录中使用来显示每个文件的 inode 编号,例如,

$ ls -li
total 0
133370 -rw-r--r-- 1 malte malte 0 Dec 30 19:00 ?2?.???љ?!?Gb??σ?[?F?
132584 -rw-r--r-- 1 malte malte 0 Dec 30 18:59 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??

接下来,使用该find实用程序按名称删除相应的文件,使用语法find <somepath> -inum <inode_number> -exec rm -i {} \;,如下例所示:

$ find . -inum 133370 -exec rm -i {} \;
rm: remove regular empty file ‘./?2?.???љ?!?Gb??σ?[?F?’? y
$ ls -li
total 0
132584 -rw-r--r-- 1 malte malte 0 Dec 30 18:59 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??

这个-i选项rm其实不是必要的,我只是添加它以防止您意外删除不想删除的文件。:)它会rm要求您对要删除的每个文件进行确认。

如果你想通过 inode 删除多个文件,你可以使用-o(意思是或者) 语法find

$ find .  \( -inum 133370 -o -inum 132584 \) -exec rm -i {} \;
rm: remove regular empty file ‘./?2?.???љ?!?Gb??σ?[?F?’? y
rm: remove regular empty file ‘./??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??’? y

您可以通过使用更多-o -inum <inode_number>表达式扩展括号中的表达式来添加更多 inode 编号。

答案2

重要的是要理解这是不是有助于解决的“文件系统损坏”问题fsck。就文件系统而言,文件名可以是任何字节序列,只要没有任何单个字节具有值 0x00(ASCII NUL,C 字符串结束标记)或 0x2F(/,目录分隔符)。(如果文件名以某种方式嵌入了 00 或 2F 字节,fsck则应修复该问题。)

相反,你所拥有的是应用程序软件(Dolphin,ls)认为包含以下字符的文件名:不可显示在您的“语言环境”中,因此它会用占位符替换它们。您不能类型这些字符也无法使用,因此操作文件会更困难,但只要您不输入或复制粘贴名称,就可以做到这一点。例如,如果您直接从 Dolphin 中删除或重命名问题文件,那应该可以正常工作(我甚至可以说,如果它不起作用,那就是 Dolphin 中的一个错误)。

如果您需要从 shell 对它们进行某些操作(例如,如果它们归 GUI 程序所有root并且因此不能被 GUI 程序修改),您可以使用“glob”模式间接命名它们,这些模式将扩展为正确的字节序列并传递下去。

现在,当然,您不会想因为 glob 模式匹配太多而意外删除东西,因此我建议使用 Perlrename实用程序将每个文件名转换为其十六进制编码:

$ rename '$_ = unpack("H*", $_)' *

这不会破坏任何信息 - 无论是文件本身,还是文件名被破坏之前可能最初编码的任何含义。可以使用以下方法撤消特定文件的操作,例如

$ rename '$_ = pack("H*", $_)' 696d706f7274616e742e646f63

注意:有两个名为 的程序rename,它们来自不同的来源;上述命令仅适用于源自 Perl 的程序。在 Ubuntu 中,您需要的是来自“rename”包的程序,而不是来自“util-linux”包的程序。 rename -h将区分:这是您想要的...

$ rename -h
Usage:
    rename [ -h|-m|-V ] [ -v ] [ -n ] [ -f ] [ -e|-E perlexpr]*|perlexpr
    [ files ]
# ...

...这不是你想要的...

$ rename -h

Usage:
 rename [options] <expression> <replacement> <file>...
# ...

要查找的关键是“perlexpr”。您可能使用的是旧版本的 Perl 重命名,无法理解上述所有选项,但我显示的命令应该仍然有效。

编辑:在 14.04.5 下,包含的 perl 脚本rename不支持 -h 开关。您可以通过检查手册页来确认您拥有正确的脚本,在man rename这种情况下,顶行将包含:

RENAME(1) Perl 程序员参考指南 RENAME(1)

答案3

我推荐 Midnight Commander - 一个基于终端的文件管理器。它是我在任何系统上安装的第一个也是最有用的软件工具。

它将允许您使用点击(如果您通过 gpm 启用了控制台鼠标功能)或使用光标和 Ins 键来选择文件。

选择文件后按 F8 删除它们

无需输入文件名或重命名文件,但您可能需要以 sudo 身份运行 Midnight Commander。

相关内容