Digamos que eu tenha uma variável com path release/linux/x86
e queira o caminho relativo de um diretório diferente (ou seja, ../../..
para o diretório de trabalho atual), como eu conseguiria isso em um comando shell (ou possivelmente no GNU Make)?
Suporte de soft link não é necessário.
Esta questão foi fortemente modificada com base na resposta aceita para melhorar a terminologia.
Responder1
Absolutamente não está claro o propósito disso, mas isso fará exatamente o que foi solicitado, usandoCaminho real GNU:
realpath -m --relative-to=release/linux/x86 .
../../..
realpath -m --relative-to=release///./linux/./x86// .
../../..
Responder2
Aqui está uma função shell que retorna um caminho relativo do diretório de origem ao destino usando apenas manipulação de strings - por meio da expansão de parâmetros do shell - sem disco ou acesso à rede. Sem nome de caminho resolução é feito.
Espera dois parâmetros, source-dir e target-dir, ambos nomes de caminho canônicos absolutos e não vazios, ambos podem ter /
terminação, nenhum deles precisa existir. Os retornos resultam em uma variável shell $REPLY
como um caminho relativo de source-dir para target-dir sem trailing /
, .
se for nulo.
O algoritmo é de uma postagem comp.unix.shell de 2005 que agora ascendeu paraarquivo.org.
pnrelpath() {
set -- "${1%/}/" "${2%/}/" '' ## '/'-end to avoid mismatch
while [ "$1" ] && [ "$2" = "${2#"$1"}" ] ## reduce $1 to shared path
do set -- "${1%/?*/}/" "$2" "../$3" ## source/.. target ../relpath
done
REPLY="${3}${2#"$1"}" ## build result
# unless root chomp trailing '/', replace '' with '.'
[ "${REPLY#/}" ] && REPLY="${REPLY%/}" || REPLY="${REPLY:-.}"
}
Usar como
$ pnrelpath "$HOME" "$PWD"
projects/incubator/nspreon
$ pnrelpath "$PWD" "$gimpkdir"
../../../.config/GIMP
$ pnrelpath "$PWD" "$(cd "$dirnm" && pwd || false)"
# using cd to resolve, canonicalize ${dirnm}
ou comURIestá compartilhando scheme://authority
,
$ pnrelpath 'https://example.com/questions/123456/how-to' 'https://example.com/media'
../../../media
Atualizar2022-11-24
Ignorar a while
instrução na função anterior retornará o que realpath --relative-base
retorna: um caminho relativo do diretório de origem para o diretório de destino se o destino estiver na origem ou abaixo dela, caso contrário, um caminho absoluto. Aplicam-se condições pré e pós semelhantes.
pnrelbase() {
set -- "${1%/}/" "${2%/}/" ## '/'-end to avoid mismatch
REPLY="${2#"$1"}" ## build result
# unless root chomp trailing '/', replace '' with '.'
[ "${REPLY#/}" ] && REPLY="${REPLY%/}" || REPLY="${REPLY:-.}"
}
(finalização da atualização)