Respostas:
Você pode usar o readlink
utilitário, com a -f
opção:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Algumas distribuições, por exemplo, as que usam o GNU coreutils e o FreeBSD , também vêm com um realpath(1)
utilitário que basicamente apenas chama realpath(3)
e faz praticamente a mesma coisa.
readlink
nem realpath
- Solaris e HP-UX, em particular.
brew install coreutils
apple.stackexchange.com/a/69332/23040 , e se você não desejar executar a etapa que redireciona todas as ferramentas padrão da CLI do Mac para os equivalentes GNU recém-instalados, basta ligar greadlink
.
Portably, a PWD
variável é definida pelo shell para um local absoluto do diretório atual. Qualquer componente desse caminho pode ser um link simbólico.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Se você deseja eliminar .
e ..
também, mude para o diretório que contém o arquivo e obtenha $PWD
lá:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
Não existe uma maneira portátil de seguir links simbólicos. Se você possui um caminho para um diretório, na maioria das unidades, ele $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
fornece um caminho que não usa links simbólicos, porque shells que rastreiam links simbólicos tendem a ser implementados pwd -P
("P" para "físico").
Alguns departamentos fornecem um utilitário para imprimir o caminho "físico" para um arquivo.
readlink -f
, assim como FreeBSD ≥8.3, NetBSD ≥4.0 e OpenBSD já em 2.2.realpath
(também está presente em alguns sistemas Linux e no BusyBox).Se o Perl estiver disponível, você poderá usar o Cwd
módulo .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? Parece que não se preocupa com stdin.
||
É pwd
adequado às suas necessidades? Fornece o caminho absoluto do diretório atual. Ou talvez o que você queira seja realpath () .
alister
e rss67
no presente artigo introduzir mais estável, compatível e maneira mais fácil. Eu nunca vi uma maneira melhor do que isso antes.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Se você quiser voltar ao local original,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
ou
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Eu desejo que isso ajude. Essa foi a melhor solução para mim.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Observe as aspas duplas em torno da substituição (para não quebrar se o caminho contiver espaços em branco e caracteres brilhantes) e o --
(caso o caminho comece com -
). Além disso, isso funciona apenas para diretórios e não canoniza links simbólicos conforme solicitado. Veja minha resposta para mais detalhes.
As outras respostas aqui foram boas, mas insuficientes para minhas necessidades. Eu precisava de uma solução que pudesse usar nos meus scripts em qualquer máquina. Minha solução foi escrever um script de shell que eu possa chamar dos scripts em que eu preciso.
#!/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 solução foi escrita para o Bourne Shell para portabilidade. Eu tenho isso em um script chamado "respath.sh".
Este script pode ser usado assim:
respath.sh '/path/to/file'
Ou assim
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
O script resolve o caminho no primeiro argumento usando o caminho do segundo argumento como ponto de partida. Se apenas o primeiro argumento for fornecido, o script resolverá o caminho relativo ao seu diretório de trabalho atual.
pwd
incorporado e não suporta -P
(o shell Bourne não implementou esse manuseio lógico de $ PWD como os shells POSIX).
cd -P --
bem no caso do 1º argumento contém alguns ..
case
cheque deve ser em ..|../*)
vez de ..*
.
dirname $cwd
Caso, além disso, você tenha algum caminho predefinido para $1
(geralmente ${PWD}
), o seguinte funcionaria:
CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
case $1 in
/*) echo "CWD=${CWD}"; ;;
*) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
esac
fi
Respeitando a resposta de todos, achei a função abaixo muito mais fácil e portátil entre o Linux / MAC OSX do que outras que encontrei em todos os lugares. Pode ajudar alguém.
#!/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
Suponha que a variável a armazene um nome de caminho (a = "tanto faz")
1. Para o caminho potencial que contém espaço:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. Para a pergunta real, ou seja, a conversão do caminho para absoluto: o readlink pode recuperar o conteúdo do link simbólico, que pode ser empregado da seguinte maneira. (a observação readlink -f
seria perfeita, mas não está disponível no mínimo no Mac OS X bash, no qual -f significa FORMATS .)
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Apenas aprendi pwd -P
em man pwd
: -P é " Exibir o diretório de trabalho físico atual (todos os links simbólicos resolvidos) " e, portanto,
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
deve funcionar também.
Conclusão: combine 1 com 2 para atender a ambos os requisitos, enquanto os nomes de caminhos que contêm espaço já são tratados nos 3 mais concisos .
-f
opção não existe no Mac OS X (pelo menos a partir de 10.8.5). Sem a-f
opção, apenas retorna um código de erro.