I would like to create a projects directory which I can access from everywhere like the home directory (~). E.g. the following should work (no matter the cwd)

  • cd projects
  • ls projects/project1

Any ideas on how I could do this?


If you're using dash, bash or ksh (and maybe some other shells - I don't remember all of them that have implemented this), you can set the CDPATH variable. From man bash:

CDPATH The search path for the cd command. This is a colon-separated list of directories in which the shell looks for destination directories specified by the cd command. A sample value is .:~:/usr.

BTW, the sample value searches the current directory, the ~ (your home directory), and then /usr, in that exact order - i.e. . comes first in that :-separated list, so has precedence over ~ and /usr.

  • CDPATH is actually a POSIX thing (see here).
    – they
    Nov 22 '21 at 7:59
  • i'm not surprised - it is in dash, after all. i don't really pay much attention to what's in posix and what isn't any more.
    – cas
    Nov 22 '21 at 11:45
  • this would only work for cd though
    – Teiem
    Nov 23 '21 at 1:36
  • yes, that's why it's called CDPATH. If you're using the terminal, get used to typing, and make use of the tab key for completion. also learn the nature and purpose of directories and directory trees. they're for organising files so you don't have everything slopped into one location, in one huge mess.
    – cas
    Nov 23 '21 at 2:13

You could create a wrapper function around cd that does a special sauce action.

  case "$1" in
      local dir="$1"
      command cd "/some/dir/${dir}" ;;
      command cd "$@" ;;

With a little generalisation, this can be expanded to handle multiple special paths, and with a little extra refinement the special path need not even form part of the destination.

To wit:

  local dir=''
  local input="${1}/" # force on / to make matches and substitutions easier
  case "${input}" in
    (projects/*) dir="/some/dir/$input" ;;
    # prj is a nick name for "projects"
    (prj/*)      dir="/some/dir/projects/${input#*/}" ;;
    (foobar/*)   dir="/another/place/$input" ;;
    # : is  a nickname for foobar
    (:/*)        dir="/another/place/foobar/${input#*/}" ;;
      command cd "$@"
  command cd "${dir}"

This allows you to specify a nickname for the target directory, taking a leaf of inspiration from the OP mention of ~ behaviour.

  • That's pretty much what $CDPATH already implements
    – roaima
    Nov 22 '21 at 8:04
  • Agreed, CDPATH is a definitely a good option here. I've updated my answer to expand on my thoughts for improvement, going beyond CDPATH functionality.
    – bxm
    Nov 22 '21 at 17:09

The tilde operator is a bit more complicated than just the home directory. See: https://datacadamia.com/lang/bash/tilde_expansion

Now, to create a variable or function that is present for all users (like PATH) add it to your system with a bash script in /etc/profile.d

For example you could have a file /etc/profile.d/00-custom-vars.sh

export PROJECT="/var/www/somesite"

and you could reference it from your shell using cd $PROJECT/html for example.

If however, you're bent on making it look like a regular folder, you could accomplish it through clever use of alias and functions in bash to write a shim for the cd command.

  • I know that I could use a variable, but I want to avoid having to type $ every time
    – Teiem
    Nov 22 '21 at 2:59
  • Then if you insist, look into something along these lines (and this will probably have some subtle mis-behavior that'll break things) function some_cd_shim() {...} alias cd=some_cd_shim see shell-tips.com/bash/alias for more info
    – haxbits
    Nov 22 '21 at 3:01
  • I would have to shim every single function and program that I ever would want to use
    – Teiem
    Nov 22 '21 at 3:10
  • Yep, that or variables, bash doesn't expand anything else without patching the source. Of course you could write an alias to handle setting up aliases, but it's generally not a good idea.
    – haxbits
    Nov 22 '21 at 3:14

To do this reliably for any/all commands you would need to modify the standard system library that handles file I/O routines. Not impossible but more complex than I wish to describe here.

The $CDPATH variable, as described in another answer here, will work perfectly for cd but will not work as a generalised solution.

You could use a variable name, project=/path/to/projectdir, and then ls $project/project1 could work. The caveat here is that an unquoted variable cannot contain whitespace. More properly you would ls "$project/project1"

Or create a symbolic link at the top of your $HOME directory, cd; ln -s /path/to/projectdir project, so that ls ~/project/project1 would work.


The expansion of ~ to your home directory is linked to user management. But tilde expansion can do more. If you would have a user named projects, the tilde ~projects would expand to that user's home directory, probably /home/projects/.

Conclusion: don't ever say I recommended this, but if you do not mind abusing your system a bit, you could add a user named projects (commands like useradd and adduser can be of help, if your distri does not have a gui for it), and give yourself full access to projects's home directory, maybe even make yourself it's owner: chown you:yourgroup ~projects/. You can even disable login for this fictitious user projects, with passwd -l projects (-l for lock). If user projects can not login, he or she will not need all the stuff that has been put in his or her home directory when it was created, so delete it all. All of this to be done as root, of course.

  • I knew about this option, but to me writing ~projects seems about as much effort as writing $projects
    – Teiem
    Nov 23 '21 at 1:35
  • You could use p as virtual username, if you want a shorter shortcut like ~p. The shortest tilde shortcut, ~, has already been taken, and other than tilde would require modifying your shell. But if you go for ~p, you could even define p's home directory as /home/yourownuser/documents/work/projects with the --home-dir HOME_DIR parameter of adduser or useradd. I guess that might interfere with some automated backup solutions that you run for all users on your computer, but if you do not have these, then go for it.
    – db-inf
    Nov 23 '21 at 10:37

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.