Respuestas:
Puede usar la readlink
utilidad, con la -f
opción:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Algunas distribuciones, por ejemplo aquellas que usan GNU coreutils y FreeBSD , también vienen con una realpath(1)
utilidad que básicamente solo llama realpath(3)
y hace casi lo mismo.
readlink
, ni realpath
- Solaris y HP-UX, en particular.
brew install coreutils
apple.stackexchange.com/a/69332/23040 , y si no desea realizar el paso que redirige todas las herramientas CLI estándar de Mac a los equivalentes GNU recién instalados, simplemente llame greadlink
.
Portablemente, el shell establece la PWD
variable en una ubicación absoluta del directorio actual. Cualquier componente de esa ruta puede ser un enlace simbólico.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Si desea eliminar .
y ..
también, cambie al directorio que contiene el archivo y obtenga $PWD
allí:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
No hay una forma portátil de seguir enlaces simbólicos. Si tiene una ruta a un directorio, en la mayoría de los dispositivos $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
proporciona una ruta que no usa enlaces simbólicos, porque los shells que rastrean enlaces simbólicos tienden a implementarse pwd -P
("P" para "físico").
Algunas unidades proporcionan una utilidad para imprimir la ruta "física" a un archivo.
readlink -f
, al igual que FreeBSD ≥8.3, NetBSD ≥4.0 y OpenBSD desde 2.2.realpath
(también está presente en algunos sistemas Linux, y está en BusyBox).Si Perl está disponible, puede usar el Cwd
módulo .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? No parece importarle el stdin.
||
¿Es pwd
adecuado para sus necesidades? Da la ruta absoluta del directorio actual. O tal vez lo que quieres es realpath () .
alister
y rss67
en este artículo presentamos la forma más estable, compatible y fácil. Nunca había visto una mejor manera que esta antes.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Si desea volver a la ubicación original,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
o
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Deseo que esto ayude. Esta fue la mejor solución para mí.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Tenga en cuenta las comillas dobles alrededor de la sustitución (para no romper si la ruta contiene espacios en blanco y caracteres globales) y la --
(en caso de que la ruta comience con -
). Además, esto solo funciona para directorios, y no canonicaliza enlaces simbólicos según lo solicitado. Vea mi respuesta para más detalles.
Las otras respuestas aquí estaban bien, pero eran insuficientes para mis necesidades. Necesitaba una solución que pudiera usar en mis scripts en cualquier máquina. Mi solución fue escribir un script de shell que pueda invocar desde los scripts donde lo necesito.
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
Esta solución está escrita para Bourne Shell para la portabilidad. Tengo esto en un script llamado "respath.sh".
Este script se puede usar así:
respath.sh '/path/to/file'
O así
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
El script resuelve la ruta en el primer argumento utilizando la ruta del segundo argumento como punto de partida. Si solo se proporciona el primer argumento, el script resuelve la ruta relativa a su directorio de trabajo actual.
pwd
incorporado y no es compatible -P
(el shell Bourne no implementó ese manejo lógico de $ PWD como lo hacen los shells POSIX).
cd -P --
también en caso de que el primer argumento contenga algo ..
case
cheque debe ser en ..|../*)
lugar de ..*
.
dirname $cwd
En caso de que, además, tenga alguna ruta predefinida para $1
(generalmente ${PWD}
), lo siguiente funcionaría:
CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
case $1 in
/*) echo "CWD=${CWD}"; ;;
*) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
esac
fi
Respetando la respuesta de todos los demás, encontré que la función a continuación es mucho más fácil y portátil entre Linux / MAC OSX que otras que encontré en todas partes. Podría ayudar a alguien.
#!/usr/bin/bash
get_absolute_path(){
file_path=`pwd $1`
echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
Suponga que la variable a almacena un nombre de ruta (a = "lo que sea")
1. Para la ruta potencial que contiene espacio:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. Para la pregunta real, es decir, convertir la ruta a absoluta: readlink puede recuperar el contenido del enlace simbólico, que puede emplearse de la siguiente manera. (la nota readlink -f
habría sido perfecta, pero no está disponible al menos en Mac OS X bash, en el que -f significa FORMATOS ).
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Acabo de aprender pwd -P
en man pwd
: -P es " Mostrar el directorio de trabajo físico actual (todos los enlaces simbólicos resueltos) " y por lo tanto
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
funcionará también.
Conclusión: combine 1 con 2 para satisfacer sus dos requisitos, mientras que los nombres de ruta que contienen espacios ya se tienen en cuenta en los 3 más concisos .
-f
interruptor no existe en Mac OS X (al menos a partir de 10.8.5). Sin el-f
interruptor, solo devuelve un código de error.