7

Sometimes it’s annoying to access a directory with the folder name. Say I have a directory named a b c d. Apart from using Tab, is there any way to access the folder without typing the name of the directory?

I know that Linux has a unique identifier every particular file. Can I use this to access the folder? I don’t know whether this can be actually done or how to do it.

I that think when Linux implements a filesystem, it compares two directory names’ uniqueness. So each directory must be unique in a space. But I think that it’s like a primary key in a database system. Is the primary key the name of the directory or is there some other unique identifier (perhaps some numbers stored “under the hood”)?

Try to think of this like a process. If you execute the command ps on a terminal, it outputs a process list with the name and number of each process. You have to call that process with the process number. Similarly, is there a number for a directory so that you could call the directory with its number instead of calling it with its name?


On further investigation, I have found that each directory has a unique inode. However, I have not so far found any built-in command to access a directory by its inode.

muru
  • 207,228
Maruf
  • 266

9 Answers9

18

Any entity in (most) file systems on Linux has an unique identifier called an inode. Notice that a file can have more than one name (hardlink), but directories have just one link in all the filesystems I know of. Notice that the concept of inode is local to the filesystem, so that in two different devices (partition or whatever) the uniqueness is not guaranteed.

You can see the inode of your directory with ls -ldi:

[:~] % ls -ldi tmp/uffa                     
20873234 drwxrwxr-x 2 romano romano 4096 Jun 26  2014 tmp/uffa

So you know that your directory has inode 20873234. Now you can switch to it with the command:

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

(Note that the 2> /dev/null is to shut up error messages about unreadable directories along the path.)

This command will scan the entirety of your home directory, so be patient.1

But what about using cd and the TAB-completion of your shell?


1. This must be the most2 inefficient thing I ever posted ... an ode to entropy. The reason is that the “primary key” under which the access to a file or directory is optimized, fast and direct is — guess what? — the pathname: /dir/dir/file_or_dir. Moreover, to grant you access to a given directory, the system needs to check all the permissions in the path... so again, accessing by inode means scanning recursively the filesystem.

2. Well, you can make thing worse by scanning from /.3

3. But then it won't work, because inodes are unique only on a per-filesystem (per-mount) basis.

Rmano
  • 32,167
8

You can make Tab rotate the available folders instead of listing them. Edit the file ~/.inputrc and add

"\C-i": menu-complete
"\e[Z": "\e-1\C-i"

If you want it for all users, edit /etc/inputrc instead.

Press Ctrl + x and Ctrl + r to make it effective.

Now use cdTab to navigate to your folder without writing its name. cdShift + Tab will rotate in the other direction.

Worth remembering that cd - will take you to the last visited folder.

Katu
  • 3,663
5

You can use shell wildcards.

For instance, I can do

cd a?b?c?d

or

cd a\*b\*c\*d

And it will expand the wildcards to the actual name and change to that directory. Assuming that's the only directory which matches.

If you have both a b c d and a1b2c3d, then cd a?b?c?d will expand to either cd a1b2c3d a b c d or cd a b c d a1b2c3d (the actual order will depend on the kernel, filesystem...), and bash will silently move you to the first path.

On the other hand, you often not have so similarly named folders, so something like a*d is enough to expand that without having to type all the intermediate characters. This is specially useful when you are not actually able to type it (eg. the names are in a different script, or even a different encoding), and you would otherwise have needed to octal-encode the filename.

muru
  • 207,228
Ángel
  • 386
3

You can find this directory in a file manager, e.g. nautilus and just drag and drop it to terminal.

If you previously type cd in terminal, you will get the command.

Pilot6
  • 92,041
2

Solution made by OP

No built-in command found here . But finally I am able to write a C program to use cd(lets call my program icd == (inode cd) ) to enter in a folder using inode value. Here I am posting the raw code.

But there is a fundamental problem I have faced here. While coding execution a C code from a bash needed to create child process under the bash process(parent process). From the child process the directory space is new, and I can not access parent process's directory space from there. So nothing could be done except invoked a new bash window from here. In future I will try to implement a new tab feature if people are interested in this. But I believe I have faced a lot of criticism for doing this. So people might not be interested. I have just done for my amusement.

RAW code is shared here,

#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 ;

}

I am using gnome terminal here. Obviously For other distro the code will be changed.

Pilot6
  • 92,041
1

Not sure if that's exactly what your asking for, but zsh has some neat tricks to access a directory by other means than typing the directory's strict name; for one, you can type a part of the name and it will expand to the directory's full name, which allows for very useful things, for example:

enter image description here

Hitting TAB...

enter image description here

kos
  • 41,268
1

The simplest way is to double click on the directory name (assuming it is visible on the screen), then type cd followed by space and click the wheel button on your mouse and it will copy and paste the directory name that you have highlighted. Pressing the enter key will then change to the directory required.

I use this procedure all the time and it's not just confined to directory names. It can be used for any commands using the command line.

Good luck.

Allen
  • 29
1

If it is just one or a few directories, why not have aliases in your bashrc or whatever init files? For example:

alias abc='cd /tmp/"a b c"'

Then whenever you want to go in there, just type abc

muru
  • 207,228
0

You could write a program to create a hash table for all of your OS directories. It would basically be a tree flattening program.

But then you could do something like hash-cd 32okjv02 and it would do the hash table lookup for the 32okjv02 to directory mapping. and jump to your directory. And it would be really fast once you got all your directories indexed.

You would have to alias mkdir to call this program every new directory and maybe write a hash-table check/refresh command you could cron every minute and on logon.