Risposte:
È possibile utilizzare l' readlink
utilità, con l' -f
opzione:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Alcune distribuzioni, ad esempio quelle che usano coreutils GNU e FreeBSD , hanno anche realpath(1)
un'utility che praticamente chiama realpath(3)
e fa praticamente la stessa cosa.
readlink
né realpath
- Solaris e HP-UX, in particolare.
brew install coreutils
apple.stackexchange.com/a/69332/23040 e se non si desidera eseguire il passaggio che reindirizza tutti gli strumenti della CLI Mac standard agli equivalenti GNU appena installati, è sufficiente chiamare greadlink
.
Portabilmente, la PWD
variabile è impostata dalla shell in una posizione assoluta della directory corrente. Qualsiasi componente di quel percorso può essere un collegamento simbolico.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Se si desidera eliminare .
e ..
anche, passare alla directory contenente il file e ottenere $PWD
lì:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
Non esiste un modo portatile per seguire i collegamenti simbolici. Se si dispone di un percorso per una directory, nella maggior parte dei casi unices $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
fornisce un percorso che non utilizza collegamenti simbolici, poiché le shell che tracciano collegamenti simbolici tendono ad implementarsi pwd -P
("P" per "fisico").
Alcuni unices forniscono un'utilità per stampare il percorso "fisico" di un file.
readlink -f
, come pure FreeBSD ≥8.3, NetBSD ≥4.0 e OpenBSD fino al 2.2.realpath
(è presente anche su alcuni sistemi Linux, ed è in BusyBox).Se Perl è disponibile, è possibile utilizzare il Cwd
modulo .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? Non sembra interessarsi allo stdin.
||
È pwd
adatto alle tue esigenze? Fornisce il percorso assoluto della directory corrente. O forse quello che vuoi è realpath () .
alister
e rss67
in questo articolo introdurre il modo più stabile, compatibile e più semplice. Non ho mai visto un modo migliore di questo prima.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Se vuoi tornare alla posizione originale,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
o
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Vorrei che questo aiuti. Questa è stata la soluzione più grande per me.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Nota le doppie virgolette intorno alla sostituzione (in modo da non interrompere se il percorso contiene spazi bianchi e caratteri globbing) e il --
(nel caso in cui il percorso inizi con -
). Inoltre, questo funziona solo per le directory e non può canonicalizzare i collegamenti simbolici come richiesto. Vedi la mia risposta per maggiori dettagli.
Le altre risposte qui andavano bene ma erano insufficienti per le mie esigenze. Avevo bisogno di una soluzione che potessi usare nei miei script su qualsiasi macchina. La mia soluzione era quella di scrivere uno script shell che posso invocare dagli script dove ne ho bisogno.
#!/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
Questa soluzione è stata scritta per la Bourne Shell per la portabilità. Ho questo in uno script chiamato "respath.sh".
Questo script può essere utilizzato in questo modo:
respath.sh '/path/to/file'
O così
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
Lo script risolve il percorso nel primo argomento utilizzando il percorso del secondo argomento come punto di partenza. Se viene fornito solo il primo argomento, lo script risolve il percorso relativo alla directory di lavoro corrente.
pwd
incorporato e non supporta -P
(la shell Bourne non ha implementato la gestione logica $ PWD come fanno le shell POSIX).
cd -P --
anche nel caso in cui il 1 ° argomento contenga alcuni ..
case
controllo dovrebbe essere ..|../*)
invece di ..*
.
dirname $cwd
Nel caso, in aggiunta, hai un percorso predefinito per $1
(di solito ${PWD}
), il seguente funzionerebbe:
CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
case $1 in
/*) echo "CWD=${CWD}"; ;;
*) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
esac
fi
Rispettando la risposta di tutti gli altri, ho trovato la seguente funzione molto più semplice e portatile tra Linux / MAC OSX rispetto ad altre che ho trovato ovunque. Potrebbe aiutare qualcuno.
#!/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
Supponiamo che la variabile a memorizzi un nome di percorso (a = "qualunque")
1. Per un potenziale percorso contenente spazio:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. Per la vera domanda, ovvero convertire il percorso in assoluto: readlink può recuperare i contenuti del link simbolico, che può essere impiegato come segue. (la nota readlink -f
sarebbe stata perfetta ma non è disponibile in almeno Mac OS X bash, in cui -f sta per FORMAT .)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Appena appreso pwd -P
in man pwd
: -P è " Visualizza la directory di lavoro corrente fisica (tutti i collegamenti simbolici risolti) " e quindi
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
deve funzionare anche.
Conclusione: combinare 1 con 2 per soddisfare entrambe le vostre esigenze, mentre i nomi di percorso contenenti spazio sono già curati in 3 più concisi .
-f
switch non esiste su Mac OS X (almeno a partire dal 10.8.5). Senza l'-f
interruttore restituisce solo un codice di errore.