Hacer pwd resultado en términos de "~"?

28

pwd me da

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

¿Hay una manera fácil de obtener

~/some/random/folder

de pwd?

Sibbs Gambling
fuente
¿La tubería a través de sed es una opción?
Matthew D. Scholefield
77
Si vas a hacer esto, yo fuertemente recomiendo nombrar el comando que resulta algo distinto pwd. De lo contrario, romperá los scripts que esperan usar su salida en contextos que no realizan una expansión de tilde.
Charles Duffy

Respuestas:

25

Si está usando bash, entonces el dirsincorporado tiene el comportamiento deseado:

dirs +0
~/some/random/folder

(Nota +0, no-0 )

Con zsh:

dirs
~/some/random/folder

Para ser exactos, primero necesitamos borrar la pila del directorio, de lo contrario dirsimprimiríamos todos los contenidos:

dirs -c; dirs

O con zshel printincorporado:

print -rD $PWD

o

print -P %~

(ese activa la expansión rápida . %~in se $PS1expande al directorio actual con $HOMEreemplazado por ~pero también maneja otros directorios con nombre como el directorio de inicio de otros usuarios o directorios con nombre que usted define).

caos
fuente
Cambio todo el tiempo entre bash y zsh. Desafortunadamente, esta solución me obliga a recordar la diferencia entre las conchas y también a recordar (verificar) dónde estoy actualmente. La respuesta de @Bichoy es agnóstica para estos dos.
avp
18

Puede usar la función de reemplazo de subcadena variable Bash:

$ pwd
/home/vagrant/foo/bar
$ echo ${PWD/#$HOME/'~'}
~/foo/bar
Nykakin
fuente
2
Esto también funciona en kshy zsh.
Sr.Spuratic
1
Si bien he votado esta respuesta porque es la forma más fácil, hay una pequeña advertencia aquí: dentro de / tmp / home / username, esto devolverá / tmp ~. No puedo encontrar una manera de insertar un signo de intercalación antes de $ HOME para solucionar esto. Si necesita que su solución sea perfecta, no use esto ...
0fnt
1
@ user18151, que tú por señalar esto. Reemplacé mi respuesta a la ${string/#substring/replacement}versión para evitar este comportamiento.
Nykakin
1
@ mr.spuratic solo es correcto (excepto por el uso de echo) en zsh. En otros shells, se $HOMEtrataría como un patrón y todo estaría sujeto a split + glob.
Stéphane Chazelas
Escapar de la tilde ('~') hizo el truco. Tenga en cuenta que \ ~ también funciona. Esto es conveniente cuando ya está en '-context: eg,PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Atafar
7

Utilizando sed:

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

La idea es utilizar cualquier carácter que sea menos probable que aparezca en una ruta de directorio de inicio como delimitador en sedregex. En el ejemplo anterior que estoy usando |.

Lo bueno de esta técnica es que en realidad es independiente de la shell.

También puede usar el alias pwdpara /bin/pwd | sed "s|$HOME|~|"obtener este comportamiento en otros scripts que podrían estar utilizando pwd.

Bichoy
fuente
2
Debe incluir el ^ancla en su expresión regular. De lo contrario, es posible (aunque poco probable) que esto reemplace un segmento en el medio del camino.
Sildoreth
En realidad, la expresión regular debería tener el siguiente aspecto "s|^/home/user\(/.*\)\?$|~\1|". De lo contrario, coincide con los caminos de otros usuarios si sus nombres son como user1, user2, user3y que coincide simplementeuser
AVP
3
tilde=\~${PWD#~}

Creo que eso es lo que quieres?

Lo bueno de la tilde es cuando se expande como un patrón que no necesita ser citado. Si se usa $HOMEde la misma manera sin comillas, se obtendrían resultados impredecibles porque cualquiera de sus caracteres constituyentes podrían ser caracteres de patrón, por lo que no siempre se generaría el resultado esperado.

Pero se espera que la expansión de tilde siempre ocurra como si fuera el resultado de una expansión citada, por lo que sus resultados son predecibles. Esto parece ser cierto en prácticamente todos los shell que he probado para casepatrones y patrones de parámetros con las notables excepciones de ambos ksh93y mkshpor cualquier motivo, ninguno de los cuales parece honrar el aspecto citado de la tilde en esa capacidad.

Otra cosa interesante de esto es que puede redefinir $HOMEpara manejar cualquier directorio de la misma manera. Por ejemplo:

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

Aquí hay otro ejemplo:

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
fuente
1
Ese es un enfoque realmente interesante. Pero se supone que $PWDestá debajo $HOME. Puede usar la misma idea combinada con la sustitución de patrones para hacerlo más general. ¿Cómo está ${PWD/#~/\~}?
Mikel
1
En realidad, la respuesta de Nykakin es básicamente eso.
Mikel
0

Puede intentar reemplazar la parte no deseada con sed:

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

o mejor:

pwd | sed "s,^$HOME,~,"
usuario1403360
fuente
1
Debe usar el ^ancla para asegurarse de que solo se reemplacen las coincidencias al comienzo de la ruta del directorio. Además, no necesita usarlo gporque el comando debería reemplazar 1 ocurrencia como máximo.
Sildoreth
Gracias. Todavía estoy aprendiendo estas cosas y tu comentario es realmente útil.
user1403360
Problemática si mi directorio de inicio es /home/alicey mi directorio actual es /home/aliceinchains. Pero si la única vez que quiero usar la función es cuando sé que soy mi directorio personal o uno de sus subdirectorios, entonces debería funcionar.
Mihai Danila