8

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.

  • 1
    wildcards work too. otherwise install zsh instead of bash – Rinzwind Aug 8 '15 at 14:25
  • Ok wildcards is not the answer I seek. need to think about zsh – Maruf Aug 8 '15 at 14:27
  • You need to access one directory like that or there's multiple ? – Sergiy Kolodyazhnyy Aug 9 '15 at 0:46
  • Add your solution (which might be interesting by the way) as an answer instead of adding it to your question. That's what answers are made for! – kos Aug 10 '15 at 23:41
  • Make that program just print the path and do a cd $(icd XXXX) --- you just rewrote that find part. Now your next task is... check what's more efficient, your program or find :-P. – Rmano Aug 11 '15 at 15:08
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.

  • 1
    If you could move to a directory within a shell script, you can source the script to accomplish what you want. The define an alias to shorten the command. – daltonfury42 Aug 12 '15 at 10:07
19

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.

  • Thanks @Romano . Actually I was thinking about the problem. I do not know that the problem would turn into such inefficient solution. But think about the solution. You can easily write a c program and put it into /bin and then try to execute it with the only inode number. I will post the code if I am able to write such think. – Maruf Aug 8 '15 at 15:20
  • 1
    and also one think I need to know. I understand the first part of this command. "$(find ~ -inum 20873234 ******)" . but I do not know Why u are writting this, "2> /dev/null". Can u please clarify once again. – Maruf Aug 8 '15 at 15:25
  • 4
    @Maruf, it will not work, efficiency-wise. 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. Your C program will need to scan the filesystem too, and find has been optimized during the last 40 years... still --- why? If you need a shortcut, use a="/my/really/strange and long/dir path name/" and then cd "$a". Can't beat it. Or use symlinks. – Rmano Aug 8 '15 at 15:26
  • 1
    A good one +1. I was at the edge of writing something similar, but I was too lazy, since the task has no sense at all. @Rmano – Pilot6 Aug 8 '15 at 15:32
  • 3
    @Rmano I would add that in general, even on a single filesystem, there may be several files that have the same inode, i.e., hardlinks. Since we are speaking about directories here, it happens to be true that each directory has a unique inode (directories cannot be hardlinked.) Also, I think the reason that one cannot directly access a file via its inode is that this would bypass any directory traversal, needed to determine whether a user is allowed to access the corresponding resource. (So if a directory could be accessed by its inode, then the kernel would have to determine its path anyway.) – Malte Skoruppa Aug 11 '15 at 0:05
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.

  • This is a good answer. Can you make it display once and then rotate? – daltonfury42 Aug 12 '15 at 9:54
  • 1
    You can assign this to another shortcut. I use Eclipse and I'm used to Ctrl + space for auto complete so I use "\C- ": menu-complete instead, leaving tab as it is. – Katu Aug 12 '15 at 22:04
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.

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.

  • Actually I am trying to do everything from terminal. :). So no need to think about nautilus. I think there must be a procedure to access the file. As Linux always save a unique identifier for a particular file. But I don't know How to do that or can this be actually done. – Maruf Aug 8 '15 at 14:10
  • It is unclear what you ask. It is not possible to change to a directory not entering its name some way. – Pilot6 Aug 8 '15 at 14:12
  • See the statement. I have updated it. – Maruf Aug 8 '15 at 14:21
  • Or if this is the problem with a single file, you could add a alias. – daltonfury42 Aug 12 '15 at 9:53
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

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.

  • This will not escape special characters – Scz Sep 15 '16 at 8:18
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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.