有时使用文件夹名称访问目录很烦人。假设我有一个名为 的目录a b c d
。除了使用Tab,还有其他方法可以访问该文件夹而无需输入目录名称吗?
我知道 Linux 为每个特定文件都设置了唯一的标识符。我可以使用它来访问文件夹吗?我不知道这是否真的可以做到或如何做到。
我认为当 Linux 实现文件系统时,它会比较两个目录名称的唯一性。因此每个目录在空间中必须是唯一的。但我认为这就像数据库系统中的主键。主键是姓名目录还是有其他一些唯一标识符(也许是一些存储在“引擎盖下”的数字)?
试着将其想象成一个进程。如果您ps
在终端上执行该命令,它会输出一个进程列表,其中包含每个进程的名称和编号。您必须使用进程编号来调用该进程。同样,目录是否有编号,以便您可以使用其编号来调用目录,而不是使用其名称来调用它?
经过进一步研究,我发现每个目录都有一个唯一的inode
。但是,到目前为止,我还没有找到任何内置命令可以通过其访问目录inode
。
答案1
Linux 上 (大多数) 文件系统中的任何实体都有一个唯一标识符,称为inode
。请注意,一个文件可以有多个名称 (硬链接),但据我所知,在所有文件系统中,目录都只有一个链接。请注意,inode 的概念是当地的到文件系统,以便在两个不同的设备(分区或其他)中无法保证唯一性。
你可以使用以下命令查看目录的 inode ls -ldi
:
[:~] % ls -ldi tmp/uffa
20873234 drwxrwxr-x 2 romano romano 4096 Jun 26 2014 tmp/uffa
因此您知道您的目录有 inode 20873234。现在您可以使用以下命令切换到它:
[:~] % cd "$(find ~ -inum 20873234 2> /dev/null)"
[:~/tmp/uffa] %
(请注意,这2> /dev/null
是为了掩盖有关路径上不可读目录的错误消息。)
此命令将扫描您的整个主目录,因此请耐心等待。1
但是如何使用cd
shell 的 TAB 补全功能呢?
1.这肯定是我发过的最没有效率的东西了……这是对熵的颂歌。原因是,优化、快速和直接访问文件或目录的“主键”是——猜猜是什么?——路径名:/dir/dir/file_or_dir
。此外,要授予您对给定目录的访问权限,系统需要检查路径中的所有权限……因此,再次强调,通过 inode 访问意味着递归扫描文件系统。
2.好吧,如果你从 扫描,情况会变得更糟/
。3
3.但这样就行不通了,因为 inode 仅在每个文件系统(每个挂载)的基础上才是唯一的。
答案2
您可以Tab轮播可用文件夹,而不是列出它们。编辑文件~/.inputrc
并添加
"\C-i": menu-complete
"\e[Z": "\e-1\C-i"
如果您希望所有用户都使用,/etc/inputrc
请进行编辑。
按Ctrl+x和Ctrl+r使其生效。
现在使用cd
Tab它导航到您的文件夹而无需写其名称。cd
Shift+Tab将向另一个方向旋转。
值得记住的是,它将cd -
带您进入最后访问的文件夹。
答案3
您可以使用 shell 通配符。
例如,我可以做
cd a?b?c?d
或者
cd a\*b\*c\*d
它会将通配符扩展为实际名称并转到该目录。假设这是唯一匹配的目录。
如果同时拥有a b c d
和a1b2c3d
,那么cd a?b?c?d
将扩展为cd a1b2c3d a b c d
或cd a b c d a1b2c3d
(实际顺序取决于内核、文件系统……),并且 bash 将默默地将您移动到第一个路径。
另一方面,您通常没有名称如此相似的文件夹,因此类似这样的内容a*d
足以扩展它,而无需键入所有中间字符。这在您实际上无法键入它时特别有用(例如,名称采用不同的脚本,甚至不同的编码),否则您将需要对文件名进行八进制编码。
答案4
OP 提出的解决方案
此处未找到内置命令。但最终我能够编写一个 C 程序来使用 cd(让我将我的程序称为 icd == (inode cd) )使用 inode 值进入文件夹。我在这里发布原始代码。
但是我在这里遇到了一个根本问题。在编写执行 Bash 中的 C 代码时,需要在 Bash 进程(父进程)下创建子进程。从子进程开始,目录空间是新的,我无法从那里访问父进程的目录空间。所以除了从这里调用一个新的 Bash 窗口外,什么也做不了。如果人们对此感兴趣,我将来会尝试实现一个新的选项卡功能。但我相信我这样做会招致很多批评。所以人们可能不感兴趣。我只是为了好玩才这么做的。
原始代码在此处共享,
#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 ;
}
我在这里使用 gnome 终端。显然对于其他发行版,代码将会改变。