How to get ~/foo from /home/user1/foo?

0

1

The Bash prompt supports the \w escape sequence, documented as

\w     the current working directory, with $HOME abbreviated
       with a tilde (uses the value of the PROMPT_DIRTRIM variable)

Is there any way to get a similar abbreviation for an arbitrary string? That is, is there a general command that does something like the following, provided that HOME=/home/user1

/home/user1         → ~
/home/user1/a/1     → ~/a/1
/home/user2/b/2     → ~user2/b/2
/root               → ~root

Sure, I could try something ugly with sed, but that is unlikely to give me the result I want in any case. :-)

The movitation behind this is that I would like to keep the titles in the tabs of my terminals as short as possible, hence abbreviate working directories where possible.

UPDATE: As there doesn’t appear to be a satisfactory solution easily available, and I would like to keep things sufficiently fast, I now went with a simple

pwd | sed -e "s|/root|~root|" -e "s|/home/user1|~|

and something similar for root. As I am the only user on the machine, this currently works more or less. I will keep the question open in case someone comes up with magical-tool-that-solves-all-problems (ideally not written in elisp…).

Claudius

Posted 2012-11-28T21:07:10.003

Reputation: 6 330

“Make everything as simple as possible, but not simpler.” — Albert Einstein.  s|/home/user1|~| will change /home/user17 to ~7. – Scott – 2012-11-30T19:01:02.653

Answers

2

For your own home directory, use dir="${PWD/#$HOME/~}".

To just strip /home/ as glenn suggests, also use dir="${dir/#\/home\//~}".


Converting other users' homedirs is much more complicated, since you have to list all users every time.

  • You can't even stop on the first match, since the few first accounts have a homedir of / which will always match. Instead, it is needed to check the longest prefix, which isn't simple.

  • I often work with servers configured to read user accounts from LDAP, which takes a whole second to list all accounts; meanwhile, Active Directory wouldn't even allow to see the entire list.

user1686

Posted 2012-11-28T21:07:10.003

Reputation: 283 655

If you want to assume that "regular" users have home directory beginning with "/home/", then case "$PWD/" in ($HOME/*) dir="${PWD/#$HOME/~}" ;; (/home/*) dir="~${PWD:6}" ;; (*) dir="$PWD" ;; esac; echo "$dir" – glenn jackman – 2012-11-28T21:40:44.253

@grawity: Yes, I can see that it is somewhat more difficult to get back than forth, but I hope dies last. @Glenn: This already fails for /root. I shall go with a hand-written list instead, but thank you very much for your interest! :) – Claudius – 2012-11-29T16:25:26.830

1

For current user, and a string stored in a variable called DIR, this will work: ${DIR/~/\~}

It replaces the expansion of ~, which is either the value of the $HOME variable or the current user's home directory, with a literal ~.

bonsaiviking

Posted 2012-11-28T21:07:10.003

Reputation: 1 563