Faire résultat pwd en termes de «~»?

28

pwd Donne moi

/data/users/me/some/random/folder

Existe-t-il un moyen facile d'obtenir

~/some/random/folder

de pwd?

Sibbs Gambling
la source
La tuyauterie à travers sed est-elle une option?
Matthew D. Scholefield
7
Si vous allez faire cela, je vous recommande fortement de nommer la commande résultante autrement que pwd. Sinon, vous casserez les scripts qui s'attendent à utiliser sa sortie dans des contextes qui n'effectuent pas l'expansion de tilde.
Charles Duffy

Réponses:

25

Si vous utilisez bash, le programme dirsintégré a le comportement souhaité:

dirs +0
~/some/random/folder

(Remarque +0, non-0 .)

Avec zsh:

dirs
~/some/random/folder

Pour être exact, nous devons d'abord vider la pile des répertoires, sinon dirs, tout le contenu serait affiché:

dirs -c; dirs

Ou avec zshde » printl'builtin:

print -rD $PWD

ou

print -P %~

(que l' on tourne l' expansion rapide sur. %~en se $PS1détend dans le répertoire courant avec $HOMEremplacé par , ~mais gère également d' autres répertoires nommés comme le répertoire d'autres utilisateurs ou répertoires nommés que vous définiriez).

le chaos
la source
Je change tout le temps entre bash et zsh. Malheureusement, cette solution m'oblige à me souvenir de la différence entre les obus et aussi à me souvenir (de vérifier) ​​où je suis actuellement. La réponse de @Bichoy est indépendante de l'environnement pour ces deux-là.
avp
18

Vous pouvez utiliser la fonction de remplacement de sous-chaîne variable Bash:

$ pwd
/home/vagrant/foo/bar
$ echo ${PWD/#$HOME/'~'}
~/foo/bar
Nykakin
la source
2
Cela fonctionne également dans kshet zsh.
mr.spuratic
1
Bien que j'aie voté pour cette réponse parce que c'est la manière la plus simple, il y a une petite mise en garde ici: à l'intérieur de / tmp / home / username, cela renverra / tmp ~. Je ne trouve pas de moyen d'insérer un signe d'insertion avant $ HOME pour résoudre ce problème. Si vous avez besoin que votre solution soit parfaite, ne l'utilisez pas ...
0fnt
1
@ user18151, que vous pour l'avoir signalé. J'ai remplacé ma réponse à la ${string/#substring/replacement}version pour éviter ce problème.
Nykakin
1
@ mr.spuratic c'est juste correct (sauf pour l'utilisation de echo) dans zsh. Dans d'autres coquilles, $HOMEserait traité comme un motif et le tout soumis à split + glob.
Stéphane Chazelas
Échapper au tilde ('~') a fait l'affaire. Notez que \ ~ fonctionne également. C'est pratique quand vous êtes déjà dans '-context: par exemple,PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Atafar
7

En utilisant sed:

pwd | sed "s|^$HOME|~|"

L'idée est d'utiliser n'importe quel caractère qui est moins susceptible d'apparaître dans un chemin de répertoire personnel comme délimiteur dans l' sedexpression régulière. Dans l'exemple ci-dessus, j'utilise |.

La bonne chose à propos de cette technique est qu'elle est en fait indépendante du shell.

Vous pouvez également créer un alias pwdpour /bin/pwd | sed "s|$HOME|~|"obtenir ce comportement dans d'autres scripts qui pourraient être utilisés pwd.

Bichoy
la source
2
Vous devez inclure l' ^ancre dans votre expression régulière. Sinon, il est possible (mais peu probable) de remplacer un segment au milieu du chemin.
Sildoreth
En fait, l'expression régulière doit ressembler à ceci "s|^/home/user\(/.*\)\?$|~\1|". Sinon , il correspond à d' autres chemins des utilisateurs si leurs noms sont comme user1, user2, user3et vous devez faire correspondreuser
AVP
3
tilde=\~${PWD#~}

Je pense que c'est ce que tu veux?

Ce qui est bien avec le tilde, c'est quand il est développé en tant que modèle, il n'a pas besoin d'être cité. L'utilisation $HOMEde la même manière sans guillemets rendrait des résultats imprévisibles car l'un de ses caractères constitutifs pourrait être des caractères de motif, et donc il pourrait ne pas toujours rendre le résultat attendu.

Mais l'expansion tilde est censée se produire toujours comme si elle était le résultat d'une expansion citée, et donc ses résultats sont prévisibles. Cela semble vrai dans pratiquement tous les shell que j'ai testés pour les casemodèles et les modèles de paramètres, à l'exception notable des deux ksh93et mkshpour quelque raison que ce soit - ni l'un ni l'autre ne semble honorer l'aspect cité du tilde à ce titre.

Une autre chose intéressante à ce sujet est que vous pouvez redéfinir $HOMEpour gérer n'importe quel répertoire du tout de la même manière. Par exemple:

cd ~
HOME=/some/prefix/I/would/like/to/trim 
#or, perhaps more usefully, some scripted means of arriving at same
tilde=\~${OLDPWD#~}
HOME=$PWD

Voici un autre exemple:

set 1 2 3 4 5 \~
cd ~; cd -; HOME= IFS=/
for d do shift
      HOME=${*#~/}/$d
      set ~ "$d" $HOME
done; cd -; HOME=$PWD
printf %s\\n "$@"
5/4/3/2/1/2/3/4/5/~/1/2/3/4/5/~
~
5
4
3
2
1
2
3
4
5
~
1
2
3
4
5
~
mikeserv
la source
1
C'est une approche vraiment intéressante. Mais il suppose que $PWDc'est en dessous $HOME. Vous pouvez utiliser la même idée combinée à la substitution de motifs pour la rendre plus générale. Comment va ${PWD/#~/\~}?
Mikel
1
En fait, la réponse de Nykakin est essentiellement cela.
Mikel
0

Vous pouvez essayer de remplacer la partie indésirable par sed:

pwd | sed 's,^/data/users/me,~,'

ou encore mieux:

pwd | sed "s,^$HOME,~,"
user1403360
la source
1
Vous devez utiliser l' ^ancre pour vous assurer que seules les correspondances au début du chemin du répertoire sont remplacées. De plus, vous n'avez pas besoin de l'utiliser gcar la commande doit remplacer au maximum 1 occurrence.
Sildoreth
Merci. J'apprends encore ces choses et votre commentaire est vraiment utile.
user1403360
Problématique si mon répertoire personnel est /home/aliceet mon répertoire actuel l'est /home/aliceinchains. Mais si la seule fois où je veux utiliser cette fonctionnalité, c'est quand je sais que je suis mon répertoire personnel ou l'un de ses sous-répertoires, cela devrait fonctionner.
Mihai Danila