una - variables de entorno linux bash
Expandir una posible ruta relativa en bash (8)
¿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.
Como argumentos para mi script, hay algunas rutas de archivos. Esos pueden, por supuesto, ser relativos (o contener ~). Pero para las funciones que he escrito, necesito caminos que sean absolutos, pero que no tengan resueltos sus enlaces simbólicos.
¿Hay alguna función para esto?
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.
Simple one-liner:
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 conseguir que sea completamente ajeno a si la ruta existe o no (para que también se pueda usar al crear archivos).
Tal vez esto sea más legible y no use una subshell 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
}
auto edición, me acabo de dar cuenta de que OP dijo que no está buscando enlaces simbólicos resueltos:
"Pero para las funciones que he escrito, necesito caminos que sean absolutos, pero que no tengan sus enlaces simbólicos resueltos".
Así que supongo que esto no es tan apropiado para su pregunta después de todo. :)
Como me he encontrado con esto muchas veces a lo largo de los años, y esta vez necesitaba una versión portátil de bash pura que pudiera usar en OSX y Linux, continué 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 probado ... ¡pero estoy abierto a comentarios!)
Puede que no sea difícil hacer que funcione para bourne shell (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
}
he aquí 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
usa esta función y devolverá la ruta real -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
en OS X puedes usar
stat -f "%N" YOUR_PATH
en Linux, es posible que tenga el ejecutable realpath
. si no, lo siguiente podría funcionar (no solo para enlaces):
readlink -c YOUR_PATH
http://www.linuxquestions.org/questions/programming-9/bash-script-return-full-path-and-filename-680368/page3.html tiene los siguientes
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 donde pwd
es útil.
MY_PATH=$(readlink -f $YOUR_ARG)
resolverá rutas relativas como "./"
y "../"
Considere esto también ( andy.wordpress.com/2008/05/09/bash-equivalent-for-php-realpath ):
#!/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