realpathno parece estar disponible en Mac (OS X 10.11 "El Capitan"). :-(
Laryx Decidua
realpathtampoco parece estar disponible en CentOS 6
user5359531
66
en osx, brew install coreutilstraerárealpath
Kevin Chen
En mi Ubuntu 18.04, realpathya está presente. No tuve que instalarlo por separado.
Acumenus
Sorprendentemente, realpathestá disponible en Git para Windows (para mí, al menos).
Andrew Keeton el
104
Si tiene instalado el paquete coreutils, generalmente puede usarlo readlink -f relative_file_namepara recuperar el absoluto (con todos los enlaces simbólicos resueltos)
El comportamiento para esto es un poco diferente de lo que pregunta el usuario, también seguirá y resolverá enlaces simbólicos recursivos en cualquier parte de la ruta. Es posible que no desee eso en algunos casos.
incipiente
1
@BradPeabody Esto funciona en una Mac si instala coreutils desde homebrew brew install coreutils. Sin embargo, el ejecutable está precedido por ag:greadlink -f relative_file_name
Miguel Isla
2
Observe que la página del manual de readlink (1) tiene como primera oración de su descripción: "Note realpath (1) es el comando preferido para la funcionalidad de canonicalización".
josch
1
puede usar -e en lugar de -f para verificar si el archivo / directorio existe o no
readlink es la solución simple para Linux, pero esta solución también funciona en OSX, por lo que +1
thetoolman
1
Este script no es equivalente a qué realpatho readlink -fhacer. Por ejemplo, no funciona en rutas donde el último componente es un enlace simbólico.
josch
2
@josch: La pregunta no es sobre la resolución de enlaces simbólicos. Pero si desea hacerlo, puede proporcionar la -Popción de pwdcomando:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Eugen Konkov
44
Me gusta la respuesta, pero solo funciona si el usuario tiene permiso para ingresar en el directorio. Esto podría no ser siempre posible.
Matthias B
34
Por lo que vale, voté por la respuesta que se eligió, pero quería compartir una solución. La desventaja es que solo es Linux: pasé unos 5 minutos tratando de encontrar el equivalente de OSX antes de llegar al desbordamiento de Stack. Sin embargo, estoy seguro de que está ahí afuera.
En Linux puedes usarlo readlink -een conjunto con dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
rendimientos
/etc/
Y luego usas dirname la hermana de, basenamepara obtener el nombre del archivo
Excelente entrada con dirname, readlinky basename. Eso me ayudó a obtener el camino absoluto de un enlace simbólico, no su objetivo.
kevinarpe
No funciona cuando desea devolver la ruta a los enlaces simbólicos (lo que simplemente necesito hacer ...).
Tomáš Zato - Restablece a Mónica el
¿Cómo podrías encontrar el camino absoluto a un camino que no existe?
sintetizadorpatel
@synthesizerpatel Muy fácilmente, habría pensado; si estoy dentro /home/GKFXy touch newfileescribo, entonces antes de presionar enter, podría resolver que me refiero a "crear / inicio / GKFX / newfile", que es una ruta absoluta a un archivo que aún no existe.
GKFX
25
Creo que este es el más portátil:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
No hay necesidad de volver a cd. Ver stackoverflow.com/a/21188136/1504556 . La suya es la mejor respuesta en esta página, en mi humilde opinión. Para aquellos interesados, el enlace ofrece una explicación de por qué funciona esta solución.
Peter
Esto no es muy portátil, dirnamees una utilidad central de GNU, no es común a todos los unixen, creo.
Oh dios mío, gracias. He estado tratando de arreglar la versión que usa ${1##*/}por un día, y ahora que reemplacé esa basura basename "$1"parece que finalmente está manejando adecuadamente las rutas que terminan en /.
l3l_aze
NB, esto no hace lo correcto con un camino que termina en../..
Alex Coventry
16
realpath es probablemente el mejor
Pero ...
La pregunta inicial fue muy confusa para comenzar, con un ejemplo mal relacionado con la pregunta como se indicó.
La respuesta seleccionada en realidad responde al ejemplo dado, y en absoluto a la pregunta en el título. El primer comando es esa respuesta (¿es realmente? Dudo), y podría funcionar también sin el '/'. Y no veo qué hace el segundo comando.
Varios problemas son mixtos:
cambiando un nombre de ruta relativo en uno absoluto, lo que sea que denote, posiblemente nada. ( Normalmente, si emite un comando como touch foo/bar, el nombre de ruta foo/bardebe existir para usted, y posiblemente debe usarse en el cálculo, antes de que el archivo se cree realmente ) .
puede haber varios nombres de ruta absolutos que denotan el mismo archivo (o archivo potencial), especialmente debido a enlaces simbólicos (enlaces simbólicos) en la ruta, pero posiblemente por otras razones (un dispositivo puede montarse dos veces como de solo lectura). Uno puede o no querer resolver explícitamente dichos enlaces simbólicos.
llegar al final de una cadena de enlaces simbólicos a un archivo o nombre sin enlace simbólico. Esto puede o no producir un nombre de ruta absoluto, dependiendo de cómo se haga. Y uno puede o no querer resolverlo en una ruta absoluta.
El comando readlink foosin opción da una respuesta solo si su argumento fooes un enlace simbólico, y esa respuesta es el valor de ese enlace simbólico. No se sigue ningún otro enlace. La respuesta puede ser una ruta relativa: cualquiera que sea el valor del argumento del enlace simbólico.
Sin embargo, readlinktiene opciones (-f -e o -m) que funcionarán para todos los archivos y le darán un nombre de ruta absoluto (el que no tiene enlaces simbólicos) al archivo realmente denotado por el argumento.
Esto funciona bien para cualquier cosa que no sea un enlace simbólico, aunque uno podría desear usar un nombre de ruta absoluto sin resolver los enlaces simbólicos intermedios en la ruta. Esto lo hace el comandorealpath -s foo
En el caso de un argumento de enlace simbólico, readlinkcon sus opciones volverá a resolver todos los enlaces simbólicos en la ruta absoluta al argumento, pero eso también incluirá todos los enlaces simbólicos que puedan encontrarse siguiendo el valor del argumento. Es posible que no desee eso si desea una ruta absoluta al enlace simbólico del argumento en sí mismo, en lugar de a lo que sea que lo vincule. Nuevamente, si fooes un enlace simbólico, realpath -s fooobtendrá una ruta absoluta sin resolver enlaces simbólicos, incluido el que se proporciona como argumento.
Sin la -sopción, realpathhace más o menos lo mismo que
readlink, excepto simplemente leer el valor de un enlace, así como varias otras cosas. Simplemente no está claro para mí por qué readlinktiene sus opciones, creando aparentemente una redundancia indeseable con
realpath .
Explorar la web no dice mucho más, excepto que puede haber algunas variaciones entre los sistemas.
Conclusión: realpathes el mejor comando para usar, con la mayor flexibilidad, al menos para el uso solicitado aquí.
Mi solución favorita fue la de @EugenKonkov porque no implicaba la presencia de otras utilidades (el paquete coreutils).
Pero falló para las rutas relativas "." y "..", así que aquí hay una versión ligeramente mejorada que maneja estos casos especiales.
Sin embargo, todavía falla si el usuario no tiene permiso para cdingresar al directorio principal de la ruta relativa.
#! /bin/sh# Takes a path argument and returns it as an absolute path. # No-op if the path is already absolute.function to-abs-path {local target="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Si está utilizando bash en Mac OS X que ni ha existido realpath ni su enlace de lectura puede imprimir la ruta absoluta, puede tener la opción de codificar su propia versión para imprimirla. Aquí está mi implementación:
(puro golpe)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(usa gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'fi}
Gracias por este fragmento de código, que podría proporcionar una ayuda limitada a corto plazo. Una explicación adecuada mejoraría en gran medida su valor a largo plazo al mostrar por qué esta es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
Toby Speight
1
Una mejora a la versión bastante agradable de @ ernest-a:
Esto trata correctamente con el caso donde se encuentra el último elemento de la ruta .., en cuyo caso la "$(pwd)/$(basename "$1")"respuesta de in @ ernest-a aparecerá como accurate_sub_path/spurious_subdirectory/...
En bash-4.3-p46, esto no funciona: el shell imprime una línea vacía cuando corrodir=`cd ".."` && echo $dir
Michael
0
Esta es una solución encadenada de todas las demás, por ejemplo, cuando realpathfalla, ya sea porque no está instalada o porque sale con un código de error, entonces, la siguiente solución se intenta hasta que se obtiene el camino correcto.
No pude encontrar una solución que fuera perfectamente portátil entre Mac OS Catalina, Ubuntu 16 y Centos 7, así que decidí hacerlo con Python en línea y funcionó bien para mis scripts de bash.
Respuestas:
utilizar:
para obtener todos los archivos o
para mostrar la ruta completa (si la ruta relativa es importante)
fuente
$(pwd)
en lugar de$PWD
? (sí, sé quepwd
es una construcción)Tratar
realpath
.Para evitar expandir los enlaces simbólicos, use
realpath -s
.La respuesta proviene del " comando bash / fish para imprimir la ruta absoluta a un archivo ".
fuente
realpath
no parece estar disponible en Mac (OS X 10.11 "El Capitan"). :-(realpath
tampoco parece estar disponible en CentOS 6brew install coreutils
traerárealpath
realpath
ya está presente. No tuve que instalarlo por separado.realpath
está disponible en Git para Windows (para mí, al menos).Si tiene instalado el paquete coreutils, generalmente puede usarlo
readlink -f relative_file_name
para recuperar el absoluto (con todos los enlaces simbólicos resueltos)fuente
brew install coreutils
. Sin embargo, el ejecutable está precedido por ag:greadlink -f relative_file_name
UPD Algunas explicaciones
"$1"
dirname "$1"
cd "$(dirname "$1")
en este directorio relativo y obtenemos la ruta absoluta al ejecutarlopwd
comando de shell$(basename "$1")
echo
sefuente
realpath
oreadlink -f
hacer. Por ejemplo, no funciona en rutas donde el último componente es un enlace simbólico.-P
opción depwd
comando:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Por lo que vale, voté por la respuesta que se eligió, pero quería compartir una solución. La desventaja es que solo es Linux: pasé unos 5 minutos tratando de encontrar el equivalente de OSX antes de llegar al desbordamiento de Stack. Sin embargo, estoy seguro de que está ahí afuera.
En Linux puedes usarlo
readlink -e
en conjunto condirname
.rendimientos
Y luego usas
dirname
la hermana de,basename
para obtener el nombre del archivorendimientos
Ponlo todo junto..
rendimientos
Estás seguro si estás apuntando a un directorio,
basename
no devolverás nada y terminarás con dos barras diagonales en la salida final.fuente
dirname
,readlink
ybasename
. Eso me ayudó a obtener el camino absoluto de un enlace simbólico, no su objetivo./home/GKFX
ytouch newfile
escribo, entonces antes de presionar enter, podría resolver que me refiero a "crear / inicio / GKFX / newfile", que es una ruta absoluta a un archivo que aún no existe.Creo que este es el más portátil:
Sin embargo, fallará si la ruta no existe.
fuente
dirname
es una utilidad central de GNU, no es común a todos los unixen, creo.dirname
es una utilidad estándar POSIX, vea aquí: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
por un día, y ahora que reemplacé esa basurabasename "$1"
parece que finalmente está manejando adecuadamente las rutas que terminan en /.../..
realpath
es probablemente el mejorPero ...
La pregunta inicial fue muy confusa para comenzar, con un ejemplo mal relacionado con la pregunta como se indicó.
La respuesta seleccionada en realidad responde al ejemplo dado, y en absoluto a la pregunta en el título. El primer comando es esa respuesta (¿es realmente? Dudo), y podría funcionar también sin el '/'. Y no veo qué hace el segundo comando.
Varios problemas son mixtos:
cambiando un nombre de ruta relativo en uno absoluto, lo que sea que denote, posiblemente nada. ( Normalmente, si emite un comando como
touch foo/bar
, el nombre de rutafoo/bar
debe existir para usted, y posiblemente debe usarse en el cálculo, antes de que el archivo se cree realmente ) .puede haber varios nombres de ruta absolutos que denotan el mismo archivo (o archivo potencial), especialmente debido a enlaces simbólicos (enlaces simbólicos) en la ruta, pero posiblemente por otras razones (un dispositivo puede montarse dos veces como de solo lectura). Uno puede o no querer resolver explícitamente dichos enlaces simbólicos.
llegar al final de una cadena de enlaces simbólicos a un archivo o nombre sin enlace simbólico. Esto puede o no producir un nombre de ruta absoluto, dependiendo de cómo se haga. Y uno puede o no querer resolverlo en una ruta absoluta.
El comando
readlink foo
sin opción da una respuesta solo si su argumentofoo
es un enlace simbólico, y esa respuesta es el valor de ese enlace simbólico. No se sigue ningún otro enlace. La respuesta puede ser una ruta relativa: cualquiera que sea el valor del argumento del enlace simbólico.Sin embargo,
readlink
tiene opciones (-f -e o -m) que funcionarán para todos los archivos y le darán un nombre de ruta absoluto (el que no tiene enlaces simbólicos) al archivo realmente denotado por el argumento.Esto funciona bien para cualquier cosa que no sea un enlace simbólico, aunque uno podría desear usar un nombre de ruta absoluto sin resolver los enlaces simbólicos intermedios en la ruta. Esto lo hace el comando
realpath -s foo
En el caso de un argumento de enlace simbólico,
readlink
con sus opciones volverá a resolver todos los enlaces simbólicos en la ruta absoluta al argumento, pero eso también incluirá todos los enlaces simbólicos que puedan encontrarse siguiendo el valor del argumento. Es posible que no desee eso si desea una ruta absoluta al enlace simbólico del argumento en sí mismo, en lugar de a lo que sea que lo vincule. Nuevamente, sifoo
es un enlace simbólico,realpath -s foo
obtendrá una ruta absoluta sin resolver enlaces simbólicos, incluido el que se proporciona como argumento.Sin la
-s
opción,realpath
hace más o menos lo mismo quereadlink
, excepto simplemente leer el valor de un enlace, así como varias otras cosas. Simplemente no está claro para mí por quéreadlink
tiene sus opciones, creando aparentemente una redundancia indeseable conrealpath
.Explorar la web no dice mucho más, excepto que puede haber algunas variaciones entre los sistemas.
Conclusión:
realpath
es el mejor comando para usar, con la mayor flexibilidad, al menos para el uso solicitado aquí.fuente
Mi solución favorita fue la de @EugenKonkov porque no implicaba la presencia de otras utilidades (el paquete coreutils).
Pero falló para las rutas relativas "." y "..", así que aquí hay una versión ligeramente mejorada que maneja estos casos especiales.
Sin embargo, todavía falla si el usuario no tiene permiso para
cd
ingresar al directorio principal de la ruta relativa.fuente
La respuesta de Eugen no funcionó para mí, pero esto sí:
Nota al margen, su directorio de trabajo actual no se ve afectado.
fuente
La mejor solución, en mi opinión, es la publicada aquí: https://stackoverflow.com/a/3373298/9724628 .
Requiere python para funcionar, pero parece cubrir todos o la mayoría de los casos extremos y ser una solución muy portátil.
fuente
En el caso de
find
, probablemente sea más fácil simplemente dar la ruta absoluta para que busque, por ejemplo:fuente
Si está utilizando bash en Mac OS X que ni ha existido realpath ni su enlace de lectura puede imprimir la ruta absoluta, puede tener la opción de codificar su propia versión para imprimirla. Aquí está mi implementación:
(puro golpe)
(usa gawk)
(puro bsd awk)
ejemplo:
fuente
Lo que dijeron, excepto
find $PWD
o (en bash)find ~+
es un poco más conveniente.fuente
Similar a la respuesta de @ ernest-a pero sin afectar
$OLDPWD
o definir una nueva función, podría disparar una subshell(cd <path>; pwd)
fuente
Si la ruta relativa es una ruta de directorio, entonces prueba la mía, debería ser la mejor:
fuente
fuente
Una mejora a la versión bastante agradable de @ ernest-a:
Esto trata correctamente con el caso donde se encuentra el último elemento de la ruta
..
, en cuyo caso la"$(pwd)/$(basename "$1")"
respuesta de in @ ernest-a aparecerá comoaccurate_sub_path/spurious_subdirectory/..
.fuente
Si desea transformar una variable que contiene una ruta relativa en una absoluta, esto funciona:
"cd" hace eco sin cambiar el directorio de trabajo, porque se ejecuta aquí en un sub-shell.
fuente
dir=`cd ".."` && echo $dir
Esta es una solución encadenada de todas las demás, por ejemplo, cuando
realpath
falla, ya sea porque no está instalada o porque sale con un código de error, entonces, la siguiente solución se intenta hasta que se obtiene el camino correcto.fuente
Puede usar la sustitución de cadena bash para cualquier ruta relativa $ line:
La sustitución básica de la parte delantera de la cadena sigue la fórmula
$ {string / # substring / replace},
que se trata bien aquí: https://www.tldp.org/LDP/abs/html/string-manipulation.html
El
\
carácter niega/
cuando queremos que sea parte de la cadena que encontramos / reemplazamos.fuente
No pude encontrar una solución que fuera perfectamente portátil entre Mac OS Catalina, Ubuntu 16 y Centos 7, así que decidí hacerlo con Python en línea y funcionó bien para mis scripts de bash.
fuente