我怎样才能摆脱这个不可见的文件?

ænd*_*rük 6 linux zfs unicode files

背景

我有一个名为akorg?. 当软件对我的文件路径的文本编码做出错误假设时,Unicode 字符让我很头疼,所以我想从名称中删除它。

问题

你会认为这很容易:

$ mv akorg? akorg
mv: cannot move ‘akorg?’ to a subdirectory of itself, ‘akorg/akorg?’
Run Code Online (Sandbox Code Playgroud)

但是——这很奇怪——它认为一个名为的文件夹akorg已经存在。我很确定没有一个:

$ ls -la
total 699K
drwxr-xr-x 15 ak ak   15 Jun 12 17:34 .
drwxr-xr-x 57 ak ak 4.0K Jun 12 17:35 ..
drwxr-xr-x 11 ak ak   21 Jun 12 16:58 akorg?
drwxr-xr-x  2 ak ak    2 May 28 20:47 Desktop
...
Run Code Online (Sandbox Code Playgroud)

尽管如此,stat否则说:

$ stat akorg
  File: ‘akorg’
  Size: 21          Blocks: 33         IO Block: 1536   directory
Device: 15h/21d Inode: 292128      Links: 11
...
Run Code Online (Sandbox Code Playgroud)

所以显然有一个不可见的文件夹。无论如何,我将删除它:

$ rmdir akorg
rmdir: failed to remove ‘akorg’: No such file or directory
Run Code Online (Sandbox Code Playgroud)

对,那么。这到底是什么东西?

到目前为止我所知道的

  • 我使用的稳定版本ZFS Linux上。这是zpool status 和 zfs 属性
  • stat返回两个相同的inodeakorgakorg?。按该 inode 搜索仅返回akorg?

    $ find . -maxdepth 1 -inum 292128
    ./akorg?
    
    Run Code Online (Sandbox Code Playgroud)
  • 更多对“隐形”文件夹不起作用的东西:

    $ rm akorg
    rm: cannot remove ‘akorg’: Is a directory
    $ unlink akorg
    unlink: cannot unlink ‘akorg’: Is a directory
    $ mv akorg akorg_temp
    mv: cannot move ‘akorg’ to ‘akorg_temp’: No such file or directory
    
    Run Code Online (Sandbox Code Playgroud)
  • 我在 Bash 4.2.45 和 zsh 5.0.0 中得到相同的结果。在这两种情况下,tab-completion akonly 返回akorg?/
  • strace的是我正确,且尝试通过命名的文件夹的前世挫败键入名字我最初的重命名的尝试印证akorg
  • 这种对更明确的重命名尝试的反应令人费解和可怕:

    $ mv --verbose --no-target-directory --no-clobber akorg? akorg
    removed ‘akorg?’
    
    Run Code Online (Sandbox Code Playgroud)

    我不明白为什么它声称已删除akorg?,或者为什么会尝试。幸运的是,lsstat akorg akorg?揭示实际上什么都没有。这是strace

  • 为了排除编码怪癖的原因,我暂时给出akorg?了一个中间名称:

    $ mv --verbose --no-target-directory --no-clobber akorg? bananas
    ‘akorg?’ -> ‘bananas’
    
    Run Code Online (Sandbox Code Playgroud)

    这按预期工作,

    $ ls -la
    total 715K
    drwxr-xr-x 16 ak ak   16 Jun 13 15:11 .
    drwxr-xr-x 57 ak ak 4.0K Jun 13 14:03 ..
    drwxr-xr-x 11 ak ak   21 Jun 12 16:58 bananas
    drwxr-xr-x  2 ak ak    2 May 28 20:47 Desktop
    ...
    
    Run Code Online (Sandbox Code Playgroud)

    但“隐形”文件夹仍然存在:

    $ stat bananas akorg
      File: ‘bananas’
      Size: 21          Blocks: 33         IO Block: 1536   directory
    Device: 15h/21d Inode: 292128      Links: 11
    ...
      File: ‘akorg’
      Size: 21          Blocks: 33         IO Block: 1536   directory
    Device: 15h/21d Inode: 292128      Links: 11
    ...
    
    Run Code Online (Sandbox Code Playgroud)

    并且mv仍然行为异常,当我尝试使用的名称akorg

    $ mv --verbose --no-target-directory --no-clobber bananas akorg
    removed ‘bananas’
    
    Run Code Online (Sandbox Code Playgroud)

Kev*_*vin 5

当您使用 zsh 时,我建议使用 Tab 补全或 shell globbing(在删除之前始终使用 echo/ls)。如果这些不起作用,您有几个选择:

通过十六进制转储检查您的文件名并用于$'...'输入它

% touch akorg?   
% ls | grep akorg | hexdump -C
00000000  61 6b 6f 72 67 e2 9c bd  0a                       |akorg....|
00000009
% ls $'akorg\xe2\x9c\xbd'  
akorg?
% rm $'akorg\xe2\x9c\xbd'
% ls
% 
Run Code Online (Sandbox Code Playgroud)

请注意,0a上面的最后一个是输入末尾的换行符,所以我们不希望它出现在我们的名字中。

使用ls -i得到的inode编号和使用find将其删除

% touch akorg?
% ls -i
6128574 akorg?
% find . -inum 6128574
akorg?
% find . -inum 6128574 -delete
% ls
% 
Run Code Online (Sandbox Code Playgroud)

您也find可以按名称(无论哪种方式,先打印!)

使用ls -b得到逃脱的名称,并输入它$'...'(这适用于非打印字符,但似乎并没有影响到你的unicode的一个,所以这是为他人作参考)。

% ls
foo?bar
% ls -b         
foo\rbar
% rm foo$'\r'bar
% ls
% 
Run Code Online (Sandbox Code Playgroud)


Run*_*ium 2

这很奇怪。(这个“答案”一开始是一条评论;),后来变得有点长。)

\n\n

看看它strace看起来没有隐藏字符或类似的东西,否则我怀疑你会在例如中看到它(这应该会导致-1 ENOENT而不是0如果一切正常的话):

\n\n
stat("akorg", {st_mode=S_IFDIR|0755, st_size=21, ...}) = 0\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如您在以下内容中所做的那样:

\n\n
lstat("akorg\\342\\234\\275", {st_mode=S_IFDIR|0755, st_size=21, ...}) = 0\n
Run Code Online (Sandbox Code Playgroud)\n\n

遇到一个邮件交换,其中一个人遇到了相反的问题ls列出文件,但stat给出ENOENT\xe2\x80\x93,尽管这是在 FreeBSD 上。

\n\n

我不太了解zfs,但是否可能某些同步、快照等失败并留下损坏的文件表?您是否创建/拥有一个名为akorg您在尝试之前删除的目录mv

\n\n

不知道您是否可以通过以下方式获取一些错误描述:

\n\n
# zpool status -v\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

要尝试的一件事是检查反向 inode 查找(可以选择添加另一个d)并检查path

\n\n
# zdb -dddd <pool-name> <inode>\n
Run Code Online (Sandbox Code Playgroud)\n\n

在名为的文件夹中baz

\n\n
# zdb -dddd qqq 31\nObject  lvl   iblk   dblk  dsize  lsize   %full  type\n    31    1    16K    512     1K    512  100.00  ZFS directory\n                                    264   bonus  ZFS znode\ndnode flags: USED_BYTES USERUSED_ACCOUNTED \ndnode maxblkid: 0\npath    /baz\nuid     1000\ngid     1000\natime   Fri Jun 14 12:39:46 2013\nmtime   Fri Jun 14 11:55:33 2013\nctime   Fri Jun 14 11:55:33 2013\ncrtime  Fri Jun 14 11:55:33 2013\ngen 1510\nmode    40775\nsize    2\nparent  3\nlinks   2\nxattr   0\nrdev    0x0000000000000000\nmicrozap: 512 bytes, 0 entries\n
Run Code Online (Sandbox Code Playgroud)\n\n

在名为 的目录中foo包含多个子目录,其中包括一个名为 的子目录akorg\xe2\x9c\xbd

\n\n
Object  lvl   iblk   dblk  dsize  lsize   %full  type\n    16    1    16K    512     1K    512  100.00  ZFS directory\n                                    264   bonus  ZFS znode\ndnode flags: USED_BYTES USERUSED_ACCOUNTED \ndnode maxblkid: 0\npath    /foo\nuid     1000\ngid     1000\natime   Fri Jun 14 13:10:38 2013\nmtime   Fri Jun 14 12:13:18 2013\nctime   Fri Jun 14 12:13:18 2013\ncrtime  Fri Jun 14 11:41:53 2013\ngen 1482\nmode    40775\nsize    6\nparent  3\nlinks   6\nxattr   0\nrdev    0x0000000000000000\nmicrozap: 512 bytes, 4 entries\n\n    foo1 = 15 (type: Directory)\n    foo2 = 18 (type: Directory)\n    foo = 19 (type: Directory)\n    akorg\xe2\x9c\xbd = 30 (type: Directory)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

通过阅读ZFS Properties ,您对各种名称 mod 的设置zfs get all storage/home-ak-annex看起来也很正常(据我所知)以及其他属性:

\n\n
storage/home-ak-annex  utf8only              off                    -\nstorage/home-ak-annex  normalization         none                   -\nstorage/home-ak-annex  casesensitivity       sensitive              -\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

如果您zfs自己构建,您可以启用调试./configure --enable-debug并使用上述内容-vvvv,包括-bbbb等。

\n\n

最后你可以在 git 上打开一个新问题。

\n

  • “已经神秘地自行解决了”……这不是一个好兆头。您的文件系统可能以某种方式损坏,尽管这很奇怪,因为文件名只存储一次。这可能是文件系统驱动程序中的错误。这也可能是由于 RAM 损坏所致——我建议运行内存测试。 (3认同)