我解压了一个损坏的 tar 文件,并设法得到了一些我无法删除的目录,如果我尝试删除它,似乎找不到它,但ls
显示它存在,无论是使用 bash 还是使用 python 我都得到类似的行为,除了在我尝试使用 删除它之后rm -rf
, ls
抱怨它找不到它,然后它列出了它(见下文rm -rf
)。该find
命令显示该文件存在,但我仍然想不出删除它的方法。
这是我的尝试:
在这里您可以看到两者ls
并find
同意我们有一个目录,
rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -print0
./mikeaâcnt
但我无法删除它:
rl]$ find -maxdepth 1 -type d -empty -print0 | xargs -0 rm -f -v
rm: cannot remove `./mikeaâ\302\201\302\204cnt': Is a directory
rl]$ ls
mikeaâ??cnt
我可以cd
,但它是空的:
rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ pwd
.../rl/mikeaâcnt
mikeaâ^Á^Äcnt]$ cd ../
rl]$ ls
mikeaâ??cnt
请看下面,这不是一个简单的文件,而是一个目录,而且在 它说找不到该文件然后直接列出它之后ls
表现得很有趣:rm -rf
rl]$ rm mikeaâ^Á^Äcnt/
rm: cannot remove `mikeaâ\302\201\302\204cnt/': Is a directory
rl]$ rm -rf mikeaâ^Á^Äcnt/
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$
这是使用 python 的尝试,找到了文件,但该名称不能用作可删除的名称:
rl]$ python
Python 2.6.6 (r266:84292, Jul 10 2013, 22:48:45)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import shutil
>>> os.listdir('.')
['mikea\xc3\xa2\xc2\x81\xc2\x84cnt']
>>> shutil.rmtree(os.listdir('.')[0] )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.6/shutil.py", line 204, in rmtree
onerror(os.listdir, path, sys.exc_info())
File "/usr/lib64/python2.6/shutil.py", line 202, in rmtree
names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'
即使当我使用制表符补全时,它选择的名称也无法使用:
rl]$ rm -rf mikeaâ^Á^Äcnt
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
使用 python 在 bash 中显示的名称我得到:
rl]$ rm -rf "mikea\xc3\xa2\xc2\x81\xc2\x84cnt"
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
我能做些什么来摆脱这个损坏的目录吗?底层文件系统(NFS)似乎可以正常工作,并且没有报告其他问题,并且在损坏的 tar 文件之前我没有遇到过此类问题。
编辑:这里使用find
自己的-exec
选项来调用rm
rl]$ find -maxdepth 1 -type d -empty -exec rm -f {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$
但文件仍然在那里,(ls
抱怨它找不到它,但还是显示了它)
第二次编辑:
rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
行为仍然不变,文件仍然存在
第三次编辑:
rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} +
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
这个名字似乎比mikeaâcnt
查看 python attempts 的输出 mikea\xc3\xa2\xc2\x81\xc2\x84cnt
和这个屏幕截图更重要:
第四次编辑:这是使用通配符的尝试:
rl]$ echo *
mikeaâcnt
rl]$ echo mike*
mikeaâcnt
rl]$ rm -rf mike*
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
和我的语言环境:
rl]$ locale
LANG=en_US.utf8
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=
第五次编辑:
rl]$ ls -i
ls: cannot access mikeaâcnt: No such file or directory
? mikeaâ??cnt
而且行为也发生了变化,现在ls
执行cd
以下操作:
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt
mikeaâcnt: No such file or directory.
这是在尝试删除后发生的,我认为这可能是答案之一中建议的 NFS 问题这里由 vinc17 提供。
lsof
第六次编辑:这是和的输出ls -a
rl]$ /usr/sbin/lsof mikeaâ^Á^äcnt lsof:mikeaâ\xc2\x81\xc2\x84cnt 上的状态错误:没有这样的文件或目录
上面是错误的,这里是正确的lsof
调用:(rl是父目录)
rl]$ /usr/sbin/lsof | grep mike | grep rl
tcsh 11926 mike cwd DIR 0,33 4096 19569249 /home/mike/mish/rl
lsof 14733 mike cwd DIR 0,33 4096 19569249 /home/mike/mish/rl
grep 14734 mike cwd DIR 0,33 4096 19569249 /home/mike/mish/rl
grep 14735 mike cwd DIR 0,33 4096 19569249 /home/mike/mish/rl
lsof 14736 mike cwd DIR 0,33 4096 19569249 /home/mike/mish/rl
rl]$
rl]$ ls -a
ls: cannot access mikeaâcnt: No such file or directory
. .. mikeaâ??cnt
第七次编辑:移动不起作用,(我在这一切之前尝试过,但我没有保存输出),但它与文件有相同的ls
问题rm
。
第八次编辑:这是按照建议使用十六进制字符:
rl]$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a mikea......cnt.
rl]$ rmdir $'mikea\6d69\6b65\61c3\a2c2\81c2\8463\6e74\0acnt'
rmdir: failed to remove `mikea\006d69\006b651c3\a2c2\\81c2\\8463\006e74': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$
第九次编辑:对于stat
命令:
rl]$ stat mikeaâ^Á^Äcnt
stat: cannot stat `mikeaâ\302\201\302\204cnt': No such file or directory
rl]$
从所有输出来看,更有可能存在评论中建议的错误或其他 NFS 不当行为。
编辑10:这是strace输出的要点,因为它太大了,它的输出或这两个命令:
strace -xx rmdir ./* | grep -e '-1 E'`
strace -xx -e trace=file ls -li`
https://gist.github.com/mikeatm/e07fa600747a4285e460
编辑11:所以在上面之前 rmdir
我注意到我可以cd
进入目录,但在之后rmdir
我不能cd
再进入,类似于昨天。和.
文件..
存在:
rl]$ ls
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ ls -a
. ..
mikeaâ^Á^Äcnt]$ cd ../
最终编辑:我看到一个本地管理员对此进行了处理,并通过登录到服务器本身并从那里删除来处理。他们的解释是,可能是名称中的字符集不合适的问题。
答案1
像这样删除文件/目录的一种方法是通过它们的索引节点引用。
要查找当前目录中元素的索引节点:
ls -i
14813568 mikeaâcnt
要删除此内容:
find . -inum 14813568 -delete
答案2
以下内容摘自这篇文章可能解释了为什么该目录拒绝被删除:
NFSv4 要求所有文件名都使用 UTF-8 通过网络进行交换。 NFSv4 规范 RFC 3530 在第 1.4.3 节中规定文件名应采用 UTF-8 编码:“略有不同的是,文件和目录名采用 UTF-8 编码以处理国际化的基础知识。”在较新的 NFS 4.1 RFC (RFC 5661) 第 1.7.3 节中也可以找到相同的文本。当前的 Linux NFS 客户端只是直接传递文件名,而不需要在当前语言环境和 UTF-8 之间进行任何转换。在使用远程 NFSv4 系统的系统上,使用非 UTF-8 文件名可能是一个真正的问题;任何遵循 NFS 规范的 NFS 服务器都应该拒绝非 UTF-8 文件名。因此,如果您想确保文件实际上可以从 Linux 客户端存储到 NFS 服务器,则当前必须使用 UTF-8 文件名。换句话说,虽然有些人认为 Linux 不会强制文件名使用特定的字符编码,但实际上在某些情况下它已经要求文件名使用 UTF-8 编码。
UTF-8 是一种长期方法。系统必须支持 UTF-8 以及许多旧的编码,让人们有时间切换到 UTF-8。要“无处不在”使用 UTF-8,所有工具都需要更新以支持 UTF-8。几年前,这是一个大问题,但截至 2011 年,这基本上是一个已解决的问题,而且我认为对于那些少数尾随系统来说,轨迹非常清晰。
并非所有字节序列都是合法的 UTF-8,并且您不需要弄清楚如何显示它们。如果内核强制执行这些限制,确保只允许使用 UTF-8 文件名,那么就没有问题...所有文件名都将是合法的 UTF-8。 Markus Kuhn 的 utf8_check C 函数可以快速确定序列是否为有效的 UTF-8。
文件系统应该要求文件名符合某些标准,不是因为某些控制人们的邪恶需要,而只是为了以后可以正确显示名称。缺乏标准使用户的事情变得更困难,而不是更容易。然而文件系统并不强制文件名采用 UTF-8,因此很容易出现垃圾。
答案3
您不应在命令行中使用非 ASCII 字符,因为如您所见,由于某种原因,它们不一定对应于文件名(Unicode 有多种方式来表达重音字母)。就像是:
rm -rf mike*
应该可以工作,因为文件名是由 shell 直接生成的。但请确保只有一个匹配项(echo mike*
首先进行确认)。
好吧,如果cd
有效,那么没有理由rm
或ls
应该说No such file or directory
,因此问题可能出在文件系统级别。
注意:不要使用ls
来查找目录是否为空,而是ls -a
.
该目录可能仍被另一个进程使用(包括如果它是某个进程的 cwd)。恕我直言,这就是为什么它仍然“存在”但可能会产生错误,例如ls
;lsof
可能会给你一些信息,但是对于 NFS,你需要找到哪台机器使用它。特别是对于 NFS,这可能会产生奇怪的错误。在某些情况下ls -a
,父目录中可以显示.nfs*
文件/目录。
当你拿到时:
$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
我怀疑该文件仍然存在于目录表由于 NFS 缓存和/或因为它被另一个进程使用,但没有关联信息。当ls
尝试获取有关文件本身的信息时,它会收到错误,因为文件本身不再存在(它仅存在于目录表中),因此会显示错误。然后ls
输出文件名,因为它位于目录表中。您在一种情况下有问号但在另一种情况下没有问号的事实是由于ls
恕我直言的显示错误(与您的问题无关)。
答案4
我相信我也遇到过同样的问题。我之前已经看到过文件名为☃
.ls
在这种情况下,文件显示为â??
,但我可以使用 删除它rm ☃
。
这导致我采用以下方法将错误的名称转换为正确的名称:
首先获取文件名的字节:
$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a mikea......cnt.
然后将这些字节解码为 UTF-8,以获取 unicode 代码点,使用此网站的十六进制输入例如:http://software.hixie.ch/utilities/cgi/unicode-decoder/utf8-decoder
U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX character (â)
U+0081 <control> character ()
U+0084 <control> character („)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character
请注意,这些都低于字节边界。我们得到以下字节:
6D 69 6B 65 61 E2 81 84 63 6E 74
如果我们以 UTF-8 处理该序列,我们会得到:
U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+2044 FRACTION SLASH character (⁄)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character
因此你的文件名是:mikea⁄cnt
,带有分数斜杠而不是普通的正斜杠。您现在可以将此名称传递给rmdir
.