Como argumentos para mi script, hay algunas rutas de archivo. Esos pueden, por supuesto, ser relativos (o contener ~). Pero para las funciones que he escrito, necesito rutas que sean absolutas, pero que no tengan sus enlaces simbólicos resueltos.
¿Hay alguna función para esto?
linux
bash
absolute-path
laar
fuente
fuente
readlink
resuelve enlaces simbólicos; el OP no quiere eso.echo $(cd some_directory && pwd)
, no resuelve el enlace simbólico, falla si algún_directorio no existe. directorio de trabajo no afectado. o asignar a una variableMY_PATH=$(cd some_directory && pwd)
.Respuestas:
MY_PATH=$(readlink -f $YOUR_ARG)
resolverá rutas relativas como"./"
y"../"
Considere esto también ( fuente ):
#!/bin/bash dir_resolve() { cd "$1" 2>/dev/null || return $? # cd to desired directory; if fail, quell any error messages but return exit status echo "`pwd -P`" # output full, link-resolved path } # sample usage if abs_path="`dir_resolve \"$1\"`" then echo "$1 resolves to $abs_path" echo pwd: `pwd` # function forks subshell, so working directory outside function is not affected else echo "Could not reach $1" fi
fuente
man pwd
: "-P Muestra el directorio de trabajo físico actual (todos los enlaces simbólicos resueltos)", simplemente elimine el-P
readlink -f
funcionalidad en OS X, puede usar Homebrew y luego ejecutar:$ brew install coreutils
Luego puede usargreadlink -f
.http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.html tiene lo siguiente
function abspath { if [[ -d "$1" ]] then pushd "$1" >/dev/null pwd popd >/dev/null elif [[ -e "$1" ]] then pushd "$(dirname "$1")" >/dev/null echo "$(pwd)/$(basename "$1")" popd >/dev/null else echo "$1" does not exist! >&2 return 127 fi }
que usa
pushd
/popd
para entrar en un estado dondepwd
es útil.fuente
DIRSTACK
y nada más. ¡Buena solución!sh
compatibilidad estándar ,pushd; cd <dir>; <cmd>; popd
se puede reemplazar con(cd <dir>; <cmd>)
.De una sola línea simple:
function abs_path { (cd "$(dirname '$1')" &>/dev/null && printf "%s/%s" "$PWD" "${1##*/}") }
Uso:
function do_something { local file=$(abs_path $1) printf "Absolute path to %s: %s\n" "$1" "$file" } do_something $HOME/path/to/some\ where
Todavía estoy tratando de descubrir cómo puedo hacer que sea completamente ajeno a si la ruta existe o no (para que también se pueda usar al crear archivos).
fuente
cd -
restablecerlo después?${1##*/}
conbasename
, sin ponerlo en una variable separada, las rutas con espacios no funcionan correctamente.$PWD
y la ejecuta, debería funcionar bastante bien: github.com/andsens/homeshick/blob/…Esto me funciona en OS X:
$(cd SOME_DIRECTORY 2> /dev/null && pwd -P)
Debería funcionar en cualquier lugar. Las otras soluciones parecían demasiado complicadas.
fuente
en OS X puedes usar
stat -f "%N" YOUR_PATH
en Linux es posible que tenga
realpath
ejecutable. de lo contrario, lo siguiente podría funcionar (no solo para los enlaces):fuente
stat -f "%N" PATH
me da exactamente el mismo camino que le di.Utilice
readlink -f <relative-path>
, por ejemploexport FULLPATH=`readlink -f ./`
fuente
Tal vez esto sea más legible y no use una subcapa y no cambie el directorio actual:
dir_resolve() { local dir=`dirname "$1"` local file=`basename "$1"` pushd "$dir" &>/dev/null || return $? # On error, return error code echo "`pwd -P`/$file" # output full, link-resolved path with filename popd &> /dev/null }
fuente
Hay otro método. Puede usar la incrustación de Python en el script bash para resolver una ruta relativa.
abs_path=$(python3 - <<END from pathlib import Path path = str(Path("$1").expanduser().resolve()) print(path) END )
fuente
autoedición, acabo de notar que el OP dijo que no está buscando enlaces simbólicos resueltos:
"Pero para las funciones que he escrito, necesito rutas que sean absolutas, pero no resuelvan sus enlaces simbólicos".
Así que supongo que, después de todo, esto no es tan apropiado para su pregunta. :)
Como me he encontrado con esto muchas veces a lo largo de los años, y esta vez necesitaba una versión portátil pura de bash que pudiera usar en OSX y Linux, seguí adelante y escribí una:
La versión viva vive aquí:
https://github.com/keen99/shell-functions/tree/master/resolve_path
pero por el bien de SO, aquí está la versión actual (creo que está bien probada ... ¡pero estoy abierto a recibir comentarios!)
Puede que no sea difícil hacerlo funcionar para bourne shell simple (sh), pero no lo intenté ... Me gusta demasiado $ FUNCNAME. :)
#!/bin/bash resolve_path() { #I'm bash only, please! # usage: resolve_path <a file or directory> # follows symlinks and relative paths, returns a full real path # local owd="$PWD" #echo "$FUNCNAME for $1" >&2 local opath="$1" local npath="" local obase=$(basename "$opath") local odir=$(dirname "$opath") if [[ -L "$opath" ]] then #it's a link. #file or directory, we want to cd into it's dir cd $odir #then extract where the link points. npath=$(readlink "$obase") #have to -L BEFORE we -f, because -f includes -L :( if [[ -L $npath ]] then #the link points to another symlink, so go follow that. resolve_path "$npath" #and finish out early, we're done. return $? #done elif [[ -f $npath ]] #the link points to a file. then #get the dir for the new file nbase=$(basename $npath) npath=$(dirname $npath) cd "$npath" ndir=$(pwd -P) retval=0 #done elif [[ -d $npath ]] then #the link points to a directory. cd "$npath" ndir=$(pwd -P) retval=0 #done else echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2 echo "opath [[ $opath ]]" >&2 echo "npath [[ $npath ]]" >&2 return 1 fi else if ! [[ -e "$opath" ]] then echo "$FUNCNAME: $opath: No such file or directory" >&2 return 1 #and break early elif [[ -d "$opath" ]] then cd "$opath" ndir=$(pwd -P) retval=0 #done elif [[ -f "$opath" ]] then cd $odir ndir=$(pwd -P) nbase=$(basename "$opath") retval=0 #done else echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2 echo "opath [[ $opath ]]" >&2 return 1 fi fi #now assemble our output echo -n "$ndir" if [[ "x${nbase:=}" != "x" ]] then echo "/$nbase" else echo fi #now return to where we were cd "$owd" return $retval }
aquí hay un ejemplo clásico, gracias a brew:
%% ls -l `which mvn` lrwxr-xr-x 1 draistrick 502 29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn
use esta función y devolverá la ruta -real-:
%% cat test.sh #!/bin/bash . resolve_path.inc echo echo "relative symlinked path:" which mvn echo echo "and the real path:" resolve_path `which mvn` %% test.sh relative symlinked path: /usr/local/bin/mvn and the real path: /usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
fuente
Si su sistema operativo lo admite, utilice:
realpath "./some/dir"
Y usándolo en una variable:
some_path="$(realpath "./some/dir")"
Que ampliará tu camino. Probado en Ubuntu y CentOS, es posible que no esté disponible en el suyo. Algunos recomiendan readlink, pero la documentación para readlink dice:
En caso de que la gente se pregunte por qué cito mis variables, es para preservar espacios en las rutas. Hacer
realpath some path
me gusta le dará dos resultados de ruta diferentes. Perorealpath "some path"
devolverá uno. Parámetros citados ftw :)fuente
¿Tienes que usar bash exclusivamente? Necesitaba hacer esto y me cansé de las diferencias entre Linux y OS X. Así que usé PHP para una solución rápida y sucia.
#!/usr/bin/php <-- or wherever <?php { if($argc!=2) exit(); $fname=$argv[1]; if(!file_exists($fname)) exit(); echo realpath($fname)."\n"; } ?>
Sé que no es una solución muy elegante, pero funciona.
fuente