bash - como canalizar o resultado do comando para cd

87

Como posso canalizar o resultado de um whichcomando para cd?

Isso é o que estou tentando fazer:

which oracle | cd
cd < which oracle

Mas nenhum deles funciona.

Existe uma maneira de fazer isso (em vez de copiar / colar, é claro)?

Edit: pensando bem, este comando falhará, porque o arquivo de destino NÃO é uma pasta / diretório .

Então, estou pensando e trabalhando em uma maneira melhor de me livrar da parte "/ oracle" final agora (sed ou awk, ou mesmo Perl) :)

Edit: Ok, isso é o que eu tenho no final:

cd `which oracle | sed 's/\/oracle//g'`
Michael Mao
fonte
2
que lhe dá comando, não diretório
Anycorn
você está tentando obter o diretório onde o programa está instalado? dirname, basename ?
Anycorn
@aaa: você está certo, acho que dirname é melhor porque aponta para "o diretório real" e não um link simbólico para o executável do oráculo ... razão pela qual meu apporach sed falharia :)
Michael Mao

Respostas:

128

Você usa o pipe nos casos em que o comando espera parâmetros da entrada padrão. ( Mais sobre isso ).

Com o cdcomando, esse não é o caso. O diretório é o argumento do comando. Nesse caso, você pode usar a substituição de comando. Use crases ou $(...)para avaliar o comando, armazene-o na variável.

path=`which oracle`
echo $path # just for debug
cd $path

embora possa ser feito de uma maneira muito mais simples:

cd `which oracle` 

ou se o seu caminho tem caracteres especiais

cd "`which oracle`"

ou

cd $(which oracle)

que é equivalente à notação de crase, mas é recomendado (crases podem ser confundidos com apóstrofos)

.. mas parece que você quer:

cd $(dirname $(which oracle))

(o que mostra que você pode usar o aninhamento facilmente)

$(...) (bem como crases) também funcionam em strings entre aspas duplas, o que ajuda quando o resultado pode eventualmente conter espaços.

cd "$(dirname "$(which oracle)")"

(Observe que ambas as saídas requerem um conjunto de aspas duplas.)

mykhal
fonte
Legal. Você poderia explicar um pouco sobre o que está acontecendo aqui? Isso parece uma desreferência de variável; existe alguma variável temporária padrão para onde vão os resultados de um comando?
Nate W.
Ahhh, esqueci-me dos acúmulos :(
Michael Mao
4
Você precisa de outro par de aspas: cd "$(dirname "$(which oracle)")".
Philipp
O |abre um novo processo, portanto, mesmo se cdlido de STDIN, cmd | cdnão funcionaria (ou seja, o diretório atual no processo original permaneceria o mesmo).
Kyle Strand,
23

Com dirname para obter o diretório:

cd $(which oracle | xargs dirname)

EDITAR: cuidado com os caminhos que contêm espaços, veja o comentário @anishpatel abaixo


fonte
2
Use cd "$(which oracle | xargs -0 dirname)"se o caminho puder conter espaços em branco. O sinalizador -0 divide a entrada por nulo em vez de espaço em branco.
anishpatel
9
cd `which oracle`

Observe que esses são crases (geralmente a tecla à esquerda de 1 em um teclado americano)

Cfreak
fonte
1
Isso não funciona se o caminho contiver espaços ou outros caracteres "especiais" e você tiver que retirar o nome do arquivo.
Philipp
@Philipp, você pode usar isso se o seu caminho tiver caracteres especiaiscd "`which oracle`"
Ram Patra
4

OK, aqui está uma solução que usa aspas corretas:

cd "$(dirname "$(which oracle)")"

Evite crases, eles são menos legíveis e sempre mencionam substituições de processos.

Philipp
fonte
2

Você não precisa de um tubo, você pode fazer o que quiser usando a expansão do parâmetro Bash!

Dica adicional: use "type -P" em vez do comando externo "which" se estiver usando o Bash.

# test
touch /ls
chmod +x /ls
cmd='ls'
PATH=/:$PATH
if cmdpath="$(type -P "$cmd")" && cmdpath="${cmdpath%/*}" ; then
   cd "${cmdpath:-/}" || { echo "Could not cd to: ${cmdpath:-/}"; exit 1; }
else
   echo "No such program in PATH search directories: ${cmd}"
   exit 1
fi
bashfu
fonte
1

Em resposta à sua pergunta editada, você pode retirar o nome do comando usando dirname:

cd $(dirname `which oracle`)
David Z
fonte
Isso não funciona se o caminho contiver espaços ou outros caracteres "especiais".
Philipp
1
Facilmente corrigido citando-o duas vezes.
David Z