如何在不写其名称的情况下 cd 到目录?

Mar*_*ruf 8 command-line files cd-command

有时访问具有文件夹名称的目录很烦人。假设我有一个名为a b c d. 除了使用 之外Tab,还有什么方法可以在不输入目录名称的情况下访问该文件夹?

我知道 Linux 每个特定文件都有一个唯一标识符。我可以用它来访问文件夹吗?我不知道这是否可以真正做到或如何做到。

我认为当 Linux 实现一个文件系统时,它会比较两个目录名称的唯一性。所以每个目录在一个空间中必须是唯一的。但我认为它就像数据库系统中的主键。主键是目录的名称还是有其他一些唯一标识符(也许是一些存储在“引擎盖下”的数字)?

试着把这想象成一个过程。如果ps在终端上执行该命令,它会输出一个进程列表,其中包含每个进程的名称和编号。您必须使用进程号调用该进程。同样,目录是否有号码,以便您可以用号码呼叫目录而不是用名称呼叫?


在进一步调查中,我发现每个目录都有一个唯一的inode. 但是,到目前为止,我还没有找到任何内置命令来通过其inode.

Rma*_*ano 19

Linux 上(大多数)文件系统中的任何实体都有一个唯一标识符,称为inode. 请注意,一个文件可以有多个名称(hardlink),但目录在我所知道的所有文件系统中只有一个链接。请注意,inode 的概念是文件系统的本地概念,因此在两个不同的设备(分区或其他)中,不能保证唯一性。

您可以使用以下命令查看目录的 inode ls -ldi

[:~] % ls -ldi tmp/uffa                     
20873234 drwxrwxr-x 2 romano romano 4096 Jun 26  2014 tmp/uffa
Run Code Online (Sandbox Code Playgroud)

所以你知道你的目录有 inode 20873234。现在你可以使用命令切换到它:

[:~] % cd "$(find ~ -inum 20873234 2> /dev/null)"  
[:~/tmp/uffa] %
Run Code Online (Sandbox Code Playgroud)

(请注意,这2> /dev/null是关闭路径中有关不可读目录的错误消息。)

此命令将扫描您的整个主目录,因此请耐心等待。1

但是如何使用cdshell 和 TAB 完成呢?


1.这一定是我发布过的最无效率的2件事……一首熵的颂歌。原因是对文件或目录的访问被优化、快速和直接的“主键”是——你猜怎么着?— 路径名:/dir/dir/file_or_dir。此外,要授予您对给定目录的访问权限,系统需要检查路径中的所有权限……同样,通过 inode 访问意味着递归扫描文件系统。

2.好吧,您可以通过从 扫描来使事情变得更糟/3

3.但是这样就行不通了,因为 inode 仅在每个文件系统(每个挂载)的基础上是唯一的。

  • @Maruf,从效率方面来说,它是行不通的。优化、快速和直接访问文件或目录的“主键”是,猜猜是什么,路径名...`/dir/dir/file_or_dir`。您的 C 程序也需要扫描文件系统,并且在过去的 40 年中,`find` 已经被优化......仍然--- 为什么?如果您需要快捷方式,请使用 `a="/my/really/strange and long/dir path name/"` 然后使用 `cd "$a"`。打不过。或者使用符号链接。 (4认同)
  • @Rmano 我会补充一点,即使在单个文件系统上,也可能有多个文件具有相同的 inode,即硬链接。由于我们在这里谈论目录,因此每个目录都有一个唯一的 inode(目录不能硬链接。)而且,我认为不能通过 inode 直接访问文件的原因是这会绕过任何目录遍历,需要判断是否允许用户访问对应的资源。(所以如果一个目录可以被它的 inode 访问,那么内核无论如何都必须确定它的路径。) (3认同)

Kat*_*atu 8

您可以Tab旋转可用文件夹而不是列出它们。编辑文件~/.inputrc并添加

"\C-i": menu-complete
"\e[Z": "\e-1\C-i"
Run Code Online (Sandbox Code Playgroud)

如果您希望所有用户都使用它,请/etc/inputrc改为编辑。

Ctrl+xCtrl+r使其生效。

现在用于cdTab导航到您的文件夹而不写其名称。cdShift+Tab将向另一个方向旋转。

值得记住的是,这cd -会将您带到上次访问的文件夹。


Áng*_*gel 5

您可以使用 shell 通配符。

例如,我可以做

cd a?b?c?d
Run Code Online (Sandbox Code Playgroud)

或者

cd a\*b\*c\*d
Run Code Online (Sandbox Code Playgroud)

它会将通配符扩展为实际名称并更改为该目录。假设这是唯一匹配的目录。

如果您同时拥有a b c dand a1b2c3dcd a?b?c?d则将扩展为cd a1b2c3d a b c dor cd a b c d a1b2c3d(实际顺序将取决于内核、文件系统...),并且 bash 会默默地将您移动到第一个路径。

另一方面,您通常没有名称如此相似的文件夹,因此类似的a*d内容足以扩展它而无需键入所有中间字符。当您实际上无法键入它时(例如,名称在不同的脚本中,甚至不同的编码),这特别有用,否则您将需要对文件名进行八进制编码。


Pil*_*ot6 2

OP提出的解决方案

此处未找到内置命令。但最终我能够编写一个 C 程序来使用 cd (让我们调用我的程序 icd == (inode cd) )使用 inode 值进入文件夹。我在这里发布原始代码。

但我在这里遇到了一个根本问题。在从 bash 编码执行 C 代码时,需要在 bash 进程(父进程)下创建子进程。从子进程中,目录空间是新的,我无法从那里访问父进程的目录空间。所以除了从这里调用一个新的 bash 窗口之外什么也做不了。如果人们对此感兴趣,将来我将尝试实现新的选项卡功能。但我相信我这样做遭到了很多批评。所以人们可能不感兴趣。我只是为了好玩而已。

RAW代码在这里分享,

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include<dirent.h>
#include <unistd.h>
#include <grp.h>
#include<pwd.h>

using namespace std ;

int main(int argc , char *argv[] ) {

  struct stat ITR ;

  if( argc != 2 ) {
    printf("\nWrong Command\n\n") ;
    return 1 ;
  }

  long long given_inode = 0 ;
  for( int i =0 ; argv[1][i] ; i++ ){
    given_inode *= 10 ;
    given_inode += (argv[1][i]-'0') ;
  }

//  if (stat(argv[1], &ITR) == -1) {
//    perror("stat");
//    return 1  ;
//  }

  printf("%s\n",argv[0]) ;
    char PWD[1000] ; 
    getcwd( PWD , 1000 ) ;

  DIR *d;
  struct dirent *p;
  char path[100000] ;
  d = opendir(".");
  if( d != NULL ) {
    while( (p = readdir(d))!= NULL ) {
        strcpy( path , "./" ) ;
        strcat( path, p->d_name ) ;
        stat(path, &ITR) ;
        //printf("%s --> ",path) ;
        //printf("%ld\n",ITR.st_ino) ;
        if( ITR.st_ino == given_inode ) {
          strcpy( path , "gnome-terminal --working-directory=" ) ;
          strcat( path, PWD ) ;
                    strcat( path, "/" ) ;
                    strcat( path, p->d_name ) ;
                    system(path) ; 
                    //printf("%s\n",path) ;
                    return 0 ;
        }
    }
  }
  printf("icd %lld:No such file or directory\n",given_inode) ;
  return 0 ;

}
Run Code Online (Sandbox Code Playgroud)

我在这里使用 gnome 终端。显然对于其他发行版,代码将被更改。