11

I want ~~ to point to a different directory so I can use it as a shortcut. I want it to have exactly same functionalities as ~. How can I do this?

3
  • 2
    You might be better off with zsh named directories Commented Sep 29, 2015 at 20:05
  • Just found an interesting solution to the problem superuser.com/a/565825/398328
    – user121183
    Commented Sep 29, 2015 at 20:29
  • 1
    @VarunAgw haha, Funny find, right as I had thought of the same solution. Shame. I thought i was a unique butterfly for a minute :(
    – Gravy
    Commented Sep 29, 2015 at 20:37

4 Answers 4

13

Actually, there is a way, it's not a great way, but it's a way, haha!

Add the following to your /etc/passwd file:

~:x:1111:99:special Character user:/test:/sbin/nologin

replace the 1111 as the UID with something that makes sense, replace /test with the directory you want ~~ to mimic.

99 on my system is the nobody group. I recommend you to do this to make sure it's a group with no permissions on any file that will ever get used. Theoretically with /sbin/nologin as the shell, it should not be able to be used, it also will not have an /etc/shadow entry so it won't have a password. Theoretically should be fine, but make sure that it doesn't somehow let you log in as the account.

As a side note: I am not in any way saying this is a good idea, but it will accomplish the functionality that you want.

EDIT: For completeness’ sake this was suggested by @VarunAgw:

You could add the user as normal with useradd -s /sbin/nologin -N tmp and then modify /etc/passwd and /etc/shadow to change the user tmp to ~ and change the location of the home directory.

2
  • True. good suggestion. I'm unsure how i feel about legitimizing it with a shadow entry but i suppose as long as no password is set its not really an additional risk.
    – Gravy
    Commented Sep 29, 2015 at 20:47
  • Old question/answer, I know, but it surfaced when someone asked it again yesterday (and we didn't realize it was a duplicate until the question's title was edited). I came up with almost the same answer. Note that useradd --badname --no-user-group --non-unique -u 1000 -g 1000 --shell /sbin/nologin -f0 -e0 --home-dir <desired_directory> "~" pretty much gives you everything in one command line. See my linked answer for more details on the results. Commented Jul 13, 2021 at 18:17
9

You can make use of CDPATH and put a directory literally named ~~ in one of your CDPATH components.

From man bash (but CDPATH is available even in sh)

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".

That will allow you to do cd ~~.

If you want to do things like vi ~~/someFile from anywhere in the directory tree, then you're out of luck if you insist on ~~ literally unless you hack your shell, however, you can use variables or environment variable to store your magic directories so you can do, e.g, $tilda/someFile

I usually put often-accessed files inside shortly named directories in my home directory so I can access them with paths such as ~/b or ~/l.

Naturally, you can usually replace directories with symlinks to directories as much as you want.

1

The shell's ~ tilde expansion is mostly programmable. It expands either to the user directory of the system username declared in its trailing context (and an excellent solution along these lines has already been offered), the value of the $HOME shell variable, or not at all.

So:

(HOME=/tmp; cd ~)
pwd; echo "$HOME"

/tmp
/home/mikeserv

I change $HOME all of the time, and I keep a function in my shell's environment file for resetting it:

home(){
    HOME=~$USER
    cd ~; pwd
}

If you want to use the ~ tilde in some way that doesn't refer to your home directory, then do so. Just reassign $HOME. Don't be afraid of it. $HOME is just a shell variable like any other.


Another suggestion I have is only a slight expansion on @PSkocik's excellent advice about using $CDPATH. One thing he didn't mention, though, is that you can use and alter $CDPATH inline without changing the current shell value for $CDPATH at all. For example:

mkdir -p /tmp/1/2
CDPATH=/tmp cd 1/2

/tmp/1/2

cd is necessarily a shell builtin, but it is not a POSIX special shell builtin, and so declaring the value for $CDPATH doesn't affect its current shell value. If you use it as I did above $CDPATH's value is only altered for the environment of the one cd command, and is restored to its previous value afterward. I tend to find the above technique most useful when used in combination with history completion. I'll do the above thing, change to a directory, run a few commands, then press up until I come back to my cd command and backspace a path segment or two to move elsewhere.


Now if you combine these two concepts then you can make a previously used command mean something entirely different the next time you use it.

for HOME in /tmp ~
do  mkdir -p ~/1/2
    CDPATH=~ cd 1/2
done

/tmp/1/2
/home/mikeserv/1/2
0

Works perfectly well as a bash function:

$ function ~~ { cd /tmp; }
$ pwd
/home/jackman
$ ~~
$ pwd
/tmp
$ cd -
$ pwd
/home/jackman

Here's another approach that comes a little closer (I know I'm not getting that close the to requirements)

function ~~ { echo /test; }

Then with a couple more characters:

cd `~~`/subdir
vi `~~`/file
5
  • 2
    Well, cd ~~/foo/bar isn't going to work so well, or vim ~~/foo.txt, etc...
    – derobert
    Commented Sep 29, 2015 at 20:03
  • 1
    The question is unclear. If that's the desired usage, I'd use the CDPATH variable to handle the cd case. Commented Sep 29, 2015 at 20:07
  • Agree it's not fully clear, but OP does ask for it to work like ~. And ~ is not used like a command.
    – derobert
    Commented Sep 29, 2015 at 20:09
  • I found it fairly understandable myself, if not completely spelled out. The problem with CDPATH is it doesn't work for commands outside of....CD. IE you could cd ~~ or cd ~~/testdir1 but you could not vim ~~testdir1
    – Gravy
    Commented Sep 29, 2015 at 20:17
  • you might do better with an alias that calls a function. like alias cd~='HOME=$OTHER_HOME; home(){ cd -- "$1"; HOME=~$USER; unset -f home;}; home '
    – mikeserv
    Commented Sep 29, 2015 at 22:19

You must log in to answer this question.