Obtenha o diretório de origem de um script Bash dentro do próprio script
Pergunta
Como obtenho o caminho do diretório no qual um Bash o script está localizado, dentro esse roteiro?
Por exemplo, digamos que eu queira usar um script Bash como inicializador de outro aplicativo.Quero mudar o diretório de trabalho para aquele onde o script Bash está localizado, para que eu possa operar nos arquivos desse diretório, da seguinte forma:
$ ./application
Solução
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
é uma linha útil que fornecerá o nome completo do diretório do script, não importa de onde ele esteja sendo chamado.
Funcionará desde que o último componente do caminho usado para localizar o script não seja um link simbólico (links de diretório estão OK).Se você também quiser resolver quaisquer links para o script em si, precisará de uma solução multilinhas:
#!/bin/bash
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
Este último funcionará com qualquer combinação de aliases, source
, bash -c
, links simbólicos, etc.
Cuidado:se você cd
para um diretório diferente antes de executar este trecho, o resultado pode estar incorreto!
Além disso, fique atento $CDPATH
Pegadinhas, e efeitos colaterais da saída stderr se o usuário tiver substituído cd de forma inteligente para redirecionar a saída para stderr (incluindo sequências de escape, como ao chamar update_terminal_cwd >&2
no Mac).Adicionando >/dev/null 2>&1
no final do seu cd
O comando cuidará de ambas as possibilidades.
Para entender como funciona, tente executar esta forma mais detalhada:
#!/bin/bash
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
TARGET="$(readlink "$SOURCE")"
if [[ $TARGET == /* ]]; then
echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
SOURCE="$TARGET"
else
DIR="$( dirname "$SOURCE" )"
echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
if [ "$DIR" != "$RDIR" ]; then
echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"
E imprimirá algo como:
SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
Outras dicas
Usar dirname "$0"
:
#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"
usando pwd
sozinho não funcionará se você não estiver executando o script no diretório em que ele está contido.
[matt@server1 ~]$ pwd
/home/matt
[matt@server1 ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[matt@server1 ~]$ cd /tmp
[matt@server1 tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp
O comando dirname é o mais básico, simplesmente analisando o caminho até o nome do arquivo na variável $0 (nome do script):
dirname "$0"
Mas como Matt B apontado, o caminho retornado é diferente dependendo de como o script é chamado.pwd não faz o trabalho porque apenas informa qual é o diretório atual, e não em qual diretório o script reside.Além disso, se um link simbólico para um script for executado, você obterá um caminho (provavelmente relativo) para onde o link reside, não o script real.
Alguns outros mencionaram o link de leitura comando, mas na sua forma mais simples, você pode usar:
dirname "$(readlink -f "$0")"
readlink resolverá o caminho do script para um caminho absoluto da raiz do sistema de arquivos.Portanto, quaisquer caminhos contendo pontos simples ou duplos, tils e/ou links simbólicos serão resolvidos para um caminho completo.
Aqui está um script demonstrando cada um deles, whatdir.sh:
#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"
Executando este script no meu diretório inicial, usando um caminho relativo:
>>>$ ./whatdir.sh
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat
Novamente, mas usando o caminho completo para o script:
>>>$ /Users/phatblat/whatdir.sh
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat
Agora mudando de diretório:
>>>$ cd /tmp
>>>$ ~/whatdir.sh
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat
E finalmente usando um link simbólico para executar o script:
>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}"
if ([ -h "${SCRIPT_PATH}" ]); then
while([ -h "${SCRIPT_PATH}" ]); do cd `dirname "$SCRIPT_PATH"`;
SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd > /dev/null
Funciona para todas as versões, incluindo
- quando chamado via soft link de múltiplas profundidades,
- quando o arquivo
- quando o script é chamado pelo comando "
source
"também conhecido como.
operador (ponto). - quando arg
$0
é modificado do chamador. "./script"
"/full/path/to/script"
"/some/path/../../another/path/script"
"./some/folder/script"
Alternativamente, se o próprio script bash for um link simbólico relativo você querer segui-lo e retornar o caminho completo do script vinculado:
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
if ([ -h "${SCRIPT_PATH}" ]) then
while([ -h "${SCRIPT_PATH}" ]) do cd `dirname "$SCRIPT_PATH"`; SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd > /dev/null
SCRIPT_PATH
é fornecido no caminho completo, não importa como seja chamado.
Apenas certifique-se de localizar isso no início do script.
Este comentário e código são Copyleft, licença selecionável sob a GPL2.0 ou posterior ou CC-SA 3.0 (CreativeCommons Share Alike) ou posterior.(c) 2008.Todos os direitos reservados.Nenhuma garantia de qualquer tipo.Você foi avisado.
http://www.gnu.org/licenses/gpl-2.0.txt
http://creativecommons.org/licenses/by-sa/3.0/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656
Você pode usar $BASH_SOURCE
#!/bin/bash
scriptdir=`dirname "$BASH_SOURCE"`
Observe que você precisa usar #!/bin/bash e não #!/bin/sh, pois é uma extensão bash
Isso deve servir:
DIR=$(dirname "$(readlink -f "$0")")
Funciona com links simbólicos e espaços no caminho.Veja as páginas de manual para nome do diretório e link de leitura.
Editar:
Pela faixa de comentários, parece não funcionar com Mac OS.Não tenho ideia do porquê disso.Alguma sugestão?
pwd
pode ser usado para encontrar o diretório de trabalho atual e dirname
para encontrar o diretório de um arquivo específico (o comando que foi executado é $0
, então dirname $0
deve fornecer o diretório do script atual).
No entanto, dirname
fornece precisamente a parte do diretório do nome do arquivo, que provavelmente será relativa ao diretório de trabalho atual.Se o seu script precisar alterar o diretório por algum motivo, a saída de dirname
torna-se sem sentido.
Eu sugiro o seguinte:
#!/bin/bash
reldir=`dirname $0`
cd $reldir
directory=`pwd`
echo "Directory is $directory"
Dessa forma, você obtém um diretório absoluto e não relativo.
Como o script será executado em uma instância bash separada, não há necessidade de restaurar o diretório de trabalho posteriormente, mas se você quiser voltar ao seu script por algum motivo, poderá atribuir facilmente o valor de pwd
para uma variável antes de mudar de diretório, para uso futuro.
Embora apenas
cd `dirname $0`
resolve o cenário específico da questão, acho que ter o caminho absoluto para mais é mais útil em geral.
Não acho que isso seja tão fácil quanto outros fizeram parecer.pwd não funciona, pois o diretório atual não é necessariamente o diretório com o script.$0 nem sempre contém as informações.Considere as três maneiras a seguir de invocar um script.
./script
/usr/bin/script
script
Na primeira e na terceira formas, $0 não possui as informações completas do caminho.No segundo e terceiro, pwd não funciona.A única maneira de obter o diretório da terceira maneira seria percorrer o caminho e encontrar o arquivo com a correspondência correta.Basicamente o código teria que refazer o que o sistema operacional faz.
Uma maneira de fazer o que você está pedindo seria apenas codificar os dados no diretório /usr/share e referenciá-los pelo caminho completo.Os dados não deveriam estar no diretório /usr/bin de qualquer maneira, então esta é provavelmente a coisa a fazer.
SCRIPT_DIR=$( cd ${0%/*} && pwd -P )
Isto obtém o diretório de trabalho atual no Mac OS X 10.6.6:
DIR=$(cd "$(dirname "$0")"; pwd)
$(dirname "$(readlink -f "$BASH_SOURCE")")
Estou cansado de acessar esta página repetidamente para copiar e colar a linha da resposta aceita.O problema é que não é fácil de entender e lembrar.
Aqui está um script fácil de lembrar:
DIR=$(dirname "${BASH_SOURCE[0]}") # get the directory name
DIR=$(realpath "${DIR}") # resolve its full path if need be
Isso é específico do Linux, mas você pode usar:
SELF=$(readlink /proc/$$/fd/255)
Aqui está um one-liner compatível com POSIX:
SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"`
# test
echo $SCRIPT_PATH
Eu tentei cada um deles e nenhum deles funcionou.Um estava muito perto, mas tinha um pequeno inseto que o quebrou feio;eles se esqueceram de colocar o caminho entre aspas.
Além disso, muitas pessoas presumem que você está executando o script a partir de um shell, então esqueça que quando você abre um novo script, o padrão é sua casa.
Experimente este diretório para ver o tamanho:
/var/Ninguém/Pensamento/Sobre espaços sendo/Em um diretório/Nome/E aqui está seu arquivo.text
Isso acerta, independentemente de como ou onde você o executa.
#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename "$0"`"
echo "dirname: `dirname "$0"`"
Então, para torná-lo realmente útil, veja como mudar para o diretório do script em execução:
cd "`dirname "$0"`"
espero que ajude
Aqui está a maneira simples e correta:
actual_path=$(readlink -f "${BASH_SOURCE[0]}")
script_dir=$(dirname "$actual_path")
Explicação:
${BASH_SOURCE[0]}
- o caminho completo para o script.O valor disso estará correto mesmo quando o script estiver sendo originado, por exemplo.source <(echo 'echo $0')
estampas festa, substituindo-o por${BASH_SOURCE[0]}
imprimirá o caminho completo do script.(Claro, isso pressupõe que você esteja bem em depender do Bash.)readlink -f
- Resolve recursivamente quaisquer links simbólicos no caminho especificado.Esta é uma extensão GNU e não está disponível (por exemplo) em sistemas BSD.Se você estiver executando um Mac, poderá usar o Homebrew para instalar o GNUcoreutils
e suplantar isso comgreadlink -f
.E claro
dirname
obtém o diretório pai do caminho.
Eu usaria algo assim:
# retrieve the full pathname of the called script
scriptPath=$(which $0)
# check whether the path is a link or not
if [ -L $scriptPath ]; then
# it is a link then retrieve the target path and get the directory name
sourceDir=$(dirname $(readlink -f $scriptPath))
else
# otherwise just get the directory name of the script path
sourceDir=$(dirname $scriptPath)
fi
Uma ligeira revisão da solução e-satis e 3bcdnlklvc04a apontada em a resposta deles
SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
SCRIPT_DIR="$PWD"
popd > /dev/null
}
Isso ainda deve funcionar em todos os casos listados.
EDITAR:evitar popd após falha no pushd, graças ao konsolebox
#!/bin/sh
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
PRG=`readlink "$PRG"`
done
scriptdir=`dirname "$PRG"`
$_ vale a pena mencionar como uma alternativa a $ 0.Se você estiver executando um script do bash, a resposta aceita pode ser abreviada para:
DIR="$( dirname "$_" )"
Observe que esta deve ser a primeira instrução do seu script.
Comparei muitas das respostas dadas e encontrei algumas soluções mais compactas.Eles parecem lidar com todos os casos extremos que surgem de sua combinação favorita de:
- Caminhos absolutos ou caminhos relativos
- Links virtuais de arquivos e diretórios
- Invocação como
script
,bash script
,bash -c script
,source script
, ou. script
- Espaços, tabulações, novas linhas, unicode, etc.em diretórios e/ou nome de arquivo
- Nomes de arquivos começando com um hífen
Se você estiver executando no Linux, parece que usar o proc
handle é a melhor solução para localizar a fonte totalmente resolvida do script atualmente em execução (em uma sessão interativa, o link aponta para o respectivo /dev/pts/X
):
resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"
Isso tem um pouco de feiúra, mas a correção é compacta e fácil de entender.Não estamos usando apenas primitivos bash, mas estou bem com isso porque readlink
simplifica consideravelmente a tarefa.O echo X
adiciona um X
ao final da string variável para que qualquer espaço em branco no nome do arquivo não seja consumido e a substituição do parâmetro ${VAR%X}
no final da linha se livra do X
.Porque readlink
adiciona uma nova linha própria (que normalmente seria consumida na substituição do comando se não fosse por nossos truques anteriores), temos que nos livrar disso também.Isto é mais facilmente conseguido usando o $''
esquema de cotação, que nos permite usar sequências de escape como \n
para representar novas linhas (é também assim que você pode facilmente criar diretórios e arquivos com nomes tortuosos).
O texto acima deve atender às suas necessidades de localização do script atualmente em execução no Linux, mas se você não tiver o proc
sistema de arquivos à sua disposição, ou se você estiver tentando localizar o caminho totalmente resolvido de algum outro arquivo, talvez você ache o código abaixo útil.É apenas uma ligeira modificação da linha acima.Se você estiver brincando com nomes de diretórios/arquivos estranhos, verifique a saída com ambos ls
e readlink
é informativo, como ls
produzirá caminhos "simplificados", substituindo ?
para coisas como novas linhas.
absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}
ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"
Tente usar:
real=$(realpath $(dirname $0))
Para sistemas com GNU coreutils readlink (por exemplo.Linux):
$(readlink -f "$(dirname "$0")")
Não há necessidade de usar BASH_SOURCE
quando $0
contém o nome do arquivo do script.
Então...Acredito que tenho esse.Atrasado para a festa, mas acho que alguns vão gostar de estar aqui se encontrarem esse tópico.Os comentários devem explicar.
#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.
## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
## dereference symbolic links (ala 'readlink') until the originating file
## is found. This is effectively the same function provided in stdlib.h as
## 'realpath' and on the command line in GNU 'readlink -f'.
## Neither of these tools, however, are particularly accessible on the many
## systems that do not have the GNU implementation of readlink, nor ship
## with a system compiler (not to mention the requisite knowledge of C).
## This script is written with portability and (to the extent possible, speed)
## in mind, hence the use of printf for echo and case statements where they
## can be substituded for test, though I've had to scale back a bit on that.
## It is (to the best of my knowledge) written in standard POSIX shell, and
## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have
## issues with it, though I'm not sure why; so probably best to avoid for now.
## Particularly useful (in fact, the reason I wrote this) is the fact that
## it can be used within a shell script to find the path of the script itself.
## (I am sure the shell knows this already; but most likely for the sake of
## security it is not made readily available. The implementation of "$0"
## specificies that the $0 must be the location of **last** symbolic link in
## a chain, or wherever it resides in the path.) This can be used for some
## ...interesting things, like self-duplicating and self-modifiying scripts.
## Currently supported are three errors: whether the file specified exists
## (ala ENOENT), whether its target exists/is accessible; and the special
## case of when a sybolic link references itself "foo -> foo": a common error
## for beginners, since 'ln' does not produce an error if the order of link
## and target are reversed on the command line. (See POSIX signal ELOOP.)
## It would probably be rather simple to write to use this as a basis for
## a pure shell implementation of the 'symlinks' util included with Linux.
## As an aside, the amount of code below **completely** belies the amount
## effort it took to get this right -- but I guess that's coding for you.
##===-------------------------------------------------------------------===##
for argv; do :; done # Last parameter on command line, for options parsing.
## Error messages. Use functions so that we can sub in when the error occurs.
recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name.
# Probably best not to install as 'pathfull', if you can avoid it.
pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"
## 'test and 'ls' report different status for bad symlinks, so we use this.
if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null; then
errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ]; then
recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then
dangling 1>&2; exit 1; fi
fi
## Not a link, but there might be one in the path, so 'cd' and 'pwd'.
if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then
printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0
fi
## Walk the symlinks back to the origin. Calls itself recursivly as needed.
while [ "$link" ]; do
cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
case "$newlink" in
"$link") dangling 1>&2 && exit 1 ;;
'') printf "$(pwd)/$(basename "$link")\n"; exit 0 ;;
*) link="$newlink" && pathfull "$link" ;;
esac
done
printf "$(pwd)/$(basename "$newlink")\n"
}
## Demo. Install somewhere deep in the filesystem, then symlink somewhere
## else, symlink again (maybe with a different name) elsewhere, and link
## back into the directory you started in (or something.) The absolute path
## of the script will always be reported in the usage, along with "$0".
if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"
# Yay ANSI l33t codes! Fancy.
printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m "
printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n "
printf "Recursive readlink for the authoritative file, symlink after "
printf "symlink.\n\n\n \033[4m$scriptname\033[24m\n\n "
printf " From within an invocation of a script, locate the script's "
printf "own file\n (no matter where it has been linked or "
printf "from where it is being called).\n\n"
else pathfull "$@"
fi
Experimente a seguinte solução de compatibilidade cruzada:
CWD="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"
como realpath
ou readlink
comandos nem sempre estão disponíveis (dependendo do sistema operacional) e ${BASH_SOURCE[0]}
está disponível apenas no shell bash.
Alternativamente, você pode tentar a seguinte função no bash:
realpath () {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
Esta função leva 1 argumento.Se o argumento já tiver caminho absoluto, imprima-o como está, caso contrário, imprima $PWD
variável + argumento nome do arquivo (sem ./
prefixo).
Relacionado:
Hmm, se no caminho de nome e Dirname não vai cortá -lo e caminhar no caminho é difícil (e se o pai não exportou o caminho!).No entanto, o shell precisa ter uma alça aberta em seu script e, na batida, a alça é #255.
SELF=`readlink /proc/$$/fd/255`
funciona para mim.
Para resumir muitas respostas:
Script: "/tmp/src dir/test.sh"
Calling folder: "/tmp/src dir/other"
Comandos usados
echo Script-Dir : `dirname "$(realpath $0)"`
echo Script-Dir : $( cd ${0%/*} && pwd -P )
echo Script-Dir : $(dirname "$(readlink -f "$0")")
echo
echo Script-Name : `basename "$(realpath $0)"`
echo Script-Name : `basename $0`
echo
echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`
echo Script-Dir-Relative : `dirname $0`
echo
echo Calling-Dir : `pwd`
A saída:
Script-Dir : /tmp/src dir
Script-Dir : /tmp/src dir
Script-Dir : /tmp/src dir
Script-Name : test.sh
Script-Name : test.sh
Script-Dir-Relative : ..
Script-Dir-Relative : ..
Calling-Dir : /tmp/src dir/other
Isso funciona no bash-3.2:
path="$( dirname "$( which "$0" )" )"
Aqui está um exemplo de seu uso:
Digamos que você tenha um ~/bin diretório, que está em seu $PATH.Você tem roteiro A dentro deste diretório.Isto fonteroteiro ~/bin/lib/B.Você sabe onde o script incluído está em relação ao original (o subdiretório biblioteca), mas não onde é relativo ao diretório atual do usuário.
Isso é resolvido pelo seguinte (dentro A):
source "$( dirname "$( which "$0" )" )/lib/B"
Não importa onde o usuário esteja ou como ele chama o script, isso sempre funcionará.
Nada disso funcionou para um script bash lançado pelo Finder no OS X - acabei usando:
SCRIPT_LOC="`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |
sed s:.*/Volumes/:/Volumes/:`"
Não é bonito, mas dá conta do recado.