141

I tried to make an "alias" for a path that I use often while shell scripting. I tried something, but it failed:

myFold="~/Files/Scripts/Main"
cd myFold

bash: cd: myFold: No such file or directory

How do I make it work ?
However, cd ~/Files/Scripts/Mainworks.

1
  • 1
    I made a simple CLI for the same and it is proving to be very useful in overcoming this. Hope it helps you too :) github.com/nsrCodes/cdd
    – nsrCodes
    Commented Mar 3, 2021 at 6:37

10 Answers 10

145

Since it's an environment variable (alias has a different definition in bash), you need to evaluate it with something like:

cd "${myFold}"

or:

cp "${myFold}/someFile" /somewhere/else

But I actually find it easier, if you just want the ease of switching into that directory, to create a real alias (in one of the bash startup files like .bashrc), so I can save keystrokes:

alias myfold='cd ~/Files/Scripts/Main'

Then you can just use (without the cd):

myfold

To get rid of the definition, you use unalias. The following transcript shows all of these in action:

pax> cd ; pwd ; ls -ald footy
/home/pax
drwxr-xr-x 2 pax pax 4096 Jul 28 11:00 footy

pax> footydir=/home/pax/footy ; cd "$footydir" ; pwd
/home/pax/footy

pax> cd ; pwd
/home/pax

pax> alias footy='cd /home/pax/footy' ; footy ; pwd
/home/pax/footy

pax> unalias footy ; footy
bash: footy: command not found
18
  • 1
    @bashboy, probably because you have no directory with that name. ~/some/path was an example, you should substitute the actual path you want to use. I'll change it to use your example directory so it's clearer. As to how to unassign an alias, you use the unalias command. I've also updated the answer with a transcript, including the use of that command.
    – paxdiablo
    Commented Jul 31, 2013 at 1:02
  • 4
    @goldisfine, see my parenthetical in one of the bash startup files like .bashrc. Putting the alias into a suitable startup file will ensure it's available for all sessions.
    – paxdiablo
    Commented Aug 26, 2015 at 1:26
  • 1
    @Dids, you shouldn't need to. The rules for what startup files run under various circumstances are complex but, unless you've modified the scripts or are starting a terminal in some weird way, it should run. The bash man page has all this under INVOCATION. From memory, .bashrc is sourced for interactive non-login shells. Interactive login shells source the first reasable of {~/.bash_profile, ~/.bash_login, ~/.profile} and it's usual to have something like source ~/.bashrc at the end of one of them to ensure that setup is done as well.
    – paxdiablo
    Commented Aug 27, 2022 at 8:25
  • 1
    For example, my .profile has if [ -n "$BASH_VERSION" ]; then if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc" ; fi ; fi. The checks are because the .profile file may be executed bu non-Bash shells as well.
    – paxdiablo
    Commented Aug 27, 2022 at 8:27
  • 1
    @Dids, you would be better off asking a new question as to why it doesn't work (including the actual behaviour assuming it varies from what you expect). However, for a start, I probably wouldn't be using test as the alias name since that's already a bash builtin. I'd also start the path with / so as not to be relative. A relative path will depend on your current working directory.
    – paxdiablo
    Commented Aug 29, 2022 at 14:52
120

There is a shell option cdable_vars:

cdable_vars
If this is set, an argument to the cd builtin command that is not a directory is assumed to be the name of a variable whose value is the directory to change to.

You could add this to your .bashrc:

shopt -s cdable_vars
export myFold=$HOME/Files/Scripts/Main

Notice that I've replaced the tilde with $HOME; quotes prevent tilde expansion and Bash would complain that there is no directory ~/Files/Scripts/Main.

Now you can use this as follows:

cd myFold

No $ required. That's the whole point, actually – as shown in other answers, cd "$myFold" works without the shell option. cd myFold also works if the path in myFold contains spaces, no quoting required.

This usually even works with tab autocompletion as the _cd function in bash_completion checks if cdable_vars is set – but not every implementation does it in the same manner, so you might have to source bash_completion again in your .bashrc (or edit /etc/profile to set the shell option).


Other shells have similar options, for example Zsh (cdablevars).

15
  • 2
    Is there an equivalent of this for ZSH?
    – Ryan Stull
    Commented Jul 12, 2018 at 20:06
  • 3
    @RyanStull setopt cdablevars looks like it might be, but I don't know zsh at all. Commented Jul 12, 2018 at 20:12
  • 1
    @JohnMee I'll roll your edit back, as a) the option is called differently in zsh (no underscore) b) the question tagged just Bash and c) I link to the Bash manual. I'll add a paragraph to mention the other shells, though. Commented Nov 19, 2018 at 2:35
  • 1
    Such a great answer! Thank you very much for the cdable_vars
    – Lucas P.
    Commented Nov 29, 2018 at 14:06
  • 1
    @Vladislav Notice that that breaks the completion for cd provided by bash-completion, which uses the _cd function (complete -o nospace -F _cd cd). Adding -v to that (to complete on variables) works, but can have undesired side effects – for me, it shows my complete environment when I tab complete. Commented Oct 1, 2020 at 13:14
23

Maybe it's better to use links

Soft Link

Symbolic or soft link (files or directories, more flexible and self documenting)

#      Source                            Link
ln -s /home/jake/doc/test/2000/something /home/jake/xxx

Hard Link

Hard link (files only, less flexible and not self documenting)

#    Source                            Link
ln /home/jake/doc/test/2000/something /home/jake/xxx

How to create a link to a directory

Hint: If you need not to see the link in your home you can start it with a dot . ; then it will be hidden by default then you can access it like

cd ~/.myHiddelLongDirLink
13

You can add any paths you want to the hashtable of your bash:

hash -d <CustomName>=<RealPath>

Now you will be able to cd ~<CustomName>. To make it permanent add it to your bashrc script.

Notice that this hashtable is meant to provide a cache for bash not to need to search for content everytime a command is executed, therefore this table will be cleared on events that invalidate the cache, e.g. modifying $PATH.

2
  • 2
    I think it will only work in zsh but not in bash.
    – sergej
    Commented Oct 24, 2019 at 8:41
  • 1
    This is the best answer IMHO, but it's true it works in zsh only, at least on my Ubuntu system. Commented Nov 18, 2019 at 1:01
13

First off, you need to remove the quotes:

bashboy@host:~$ myFolder=~/Files/Scripts/Main

The quotes prevent the shell from expanding the tilde to its special meaning of being your $HOME directory.

You could then use $myFolder an environment a shell variable:

bashboy@host:~$ cd $myFolder
bashboy@host:~/Files/Scripts/Main$

To make an alias, you need to define the alias:

alias myfolder="cd $myFolder"

You can then treat this sort of like a command:

bashboy@host:~$ myFolder
bashboy@host:~/Files/Scripts/Main$
3
  • It's not actually an environment variable unless you export it. Commented Jul 31, 2013 at 3:18
  • 2
    @KeithThompson Okay, it's just a shell variable. But, you don't want to export it because you don't want it to possibly affect child processes. You define it this way it in your .bashrc or whatever resource file you use, and it will be defined in the immediate shell, but not in shell scripts.
    – David W.
    Commented Jul 31, 2013 at 14:04
  • I prefer this solutions because it works with auto completition
    – Vassilis
    Commented Jun 5, 2017 at 12:54
6

First, you need the $ to access "myFold"'s value to make the code in the question work:

cd "$myFold"

To simplify this you create an alias in ~/.bashrc:

alias cdmain='cd ~/Files/Scripts/Main'

Don't forget to source the .bashrc once to make the alias become available in the current bash session:

source ~/.bashrc

Now you can change to the folder using:

cdmain
5

Another option would be to use a symbolic link. ie:

ln -s ~/Files/Scripts/Main ~/myFold

After that you can perform operations to ~/myFold, such as:

cp some_file.txt ~/myFold

which will put the file in ~/Files/Scripts/Main. You can remove the symbolic link at any time with rm ~/myFold, which will keep the original directory.

2
  • One downside: If you cd myFold then pwd, it will show you're in myFold. This is a deal breaker for me because relative commands with p4 source control depend on the current directory.
    – User5910
    Commented Mar 15, 2018 at 17:46
  • 1
    @User5910 - use pwd -P
    – dvj
    Commented Jun 22, 2018 at 0:42
4

The preceding answers that I tried do not allow for automatic expansion (autocompletion) of subdirectories of the aliased directory.

However, if you push the directory that you want to alias onto the dirs stack...

$ pushd ~/my/aliased/dir

...you can then type dirs -v to see its numeric position in the stack:

 0  ~/my/aliased/dir
 1  ~/Downloads
 2  /media/usbdrive

and refer to it using that number for most if not all commands that expect a directory parameter:

 $ mv foo.txt ~0  

You can even use Tab to show the immediate subdirectories of the "aliased" directory:

 $ cd ~0/<Tab>
 child_dir1    child_dir2
3

but an actual alias for a dir is also possible, try

 myScripts="~/Files/Scripts/Main"
 alias myScripts="cd $myScripts"

This way you have a common naming convention (for each dir/alias pair), and if you need to copy something from the current dir to myScripts, you don't have to think about it.

IHTH

-1

Put the following line in your myscript

set myFold = '~/Files/Scripts/Main'

In the terminal use

source myscript
cd $myFold

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