Como retornar o diretório de um determinado executável?

4

Se eu quiser retornar o caminho de um determinado executável, posso executar:

which mysql

Que retorna por exemplo:

/usr/bin/mysql

Gostaria de retornar apenas:

/usr/bin

Como posso fazer isso?

    
por Benjamin 01.08.2013 / 16:44

5 respostas

7
executable=mysql

executable_path=$(command -v -- "$executable") &&
  dirname -- "$executable_path"

( não use which ).

Claro, isso não funcionará se $executable for um shell embutido, função ou alias. Não tenho conhecimento de nenhum shell em que mysql seja interno. Não será uma função ou alias, a menos que você os tenha definido anteriormente, mas então você deve saber sobre isso. Uma exceção a isso poderia ser bash , que suporta funções exportadas.

$ bash -c 'command -v mysql'
/usr/bin/mysql
$ mysql='() { echo test;}' bash -c 'command -v mysql'
mysql
    
por 01.08.2013 / 16:49
4

que

Em geral, este comando deve ser evitado.

Por quê?

Porque ele usa seu ambiente atual ao construir o $PATH que será avaliado ao procurar executáveis. Isso pode causar confusão ao lidar com scripts de shell e outros, que potencialmente usarão o $PATH conforme construído pelos arquivos ~/.bashrc e ~/.bash_profile quando executados.

Por exemplo:

# path to start
$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/sam/bin

# let's change it
$ export PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

$ echo $PATH
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin

# simulate a new env. for a shell script
$ bash -lc "echo \$PATH"
/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/sam/bin

Observe que o script de shell, se executado, teria o ambiente original, não o atual!

tipo

Você também pode usar o comando type para localizar executáveis em seu ambiente:

$ type ls
ls is aliased to 'ls --color=auto'

Ou para ver tudo, use a opção -a :

$ type -a ls
ls is aliased to 'ls --color=auto'
ls is /bin/ls

type mostrará os aliases e o local. Para encontrar o diretório, a solução @StephaneChazelas de usar command é melhor.

whereis

Você também pode usar o comando whereis , mas isso não usa seu ambiente, ele possui um conjunto de diretórios codificados que ele procura. Consulte man whereis para mais detalhes.

localizar

Este pode confundir as pessoas, mas algumas distros incluem uma ferramenta que é executada a partir de um cron job, normalmente diário, que varre todo o disco e constrói um pequeno arquivo de banco de dados que você pode procurar usando o comando locate .

  • O cron job é chamado /etc/cron.daily/mlocate.cron no meu sistema Fedora 14.
  • A ferramenta que faz a varredura é chamada /usr/bin/updatedb .
  • O arquivo DB está localizado aqui: /var/lib/mlocate/mlocate.db .

Usando o que eu considero um pouco como uma invasão, você pode persuadir o locate a procurar apenas os arquivos com o nome ls da seguinte forma:

$ locate -b '\ls'
/bin/ls
/usr/share/javadoc/java-1.6.0-openjdk/api/org/w3c/dom/ls
/usr/share/javadoc/java-1.6.0-openjdk/jre/api/plugin/dom/org/w3c/dom/ls
/usr/share/locale/l10n/ls
/var/cache/abrt-di/usr/src/debug/gcc-4.5.1-20100924/libjava/classpath/external/w3c_dom/org/w3c/dom/ls
/var/cache/abrt-di/usr/src/debug/gcc-4.5.1-20100924/libjava/classpath/gnu/xml/dom/ls

O exemplo acima funciona porque você é \ é um caractere de globbing, portanto, isso desativa a substituição implícita de ls por *ls* .

Consulte a página de localização do manual para obter mais detalhes.

whatis

Uma ferramenta menos conhecida é chamada whatis . Este é semelhante a locate , então é apoiado por um banco de dados. É útil para descobrir comandos, no entanto:

$ whatis ls
ls                   (1)  - list directory contents
ls                   (1p)  - list directory contents

A ferramenta é invocada a partir de uma tarefa agendada, /etc/cron.daily/makewhatis.cron . No entanto, makewhatis constrói seu banco de dados a partir das páginas man em seu sistema.

Você pode ver mais sobre isso nas páginas do makewhatis man .

Apenas o nome do diretório?

Você pode usar o comando dirpath contra qualquer saída produzida pelos comandos que mencionei acima para obter apenas o componente de diretório.

dirpath não faz nenhuma verificação para que você possa fornecer praticamente qualquer tipo de caminho para um arquivo e ele lhe dará a parte do diretório:

$ dirname /some/path/to/a/script
/some/path/to/a
    
por 01.08.2013 / 17:06
1

É bastante simples com xargs:

which mysql | xargs dirname
    
por 02.08.2013 / 03:56
0

dirname é a maneira mais simples de conseguir isso:

$ which mysql
/usr/bin/mysql
$ dirname 'which mysql'
/usr/bin
    
por 02.08.2013 / 09:09
0

Como outros ter explicado , não use which .

Você pode escrever uma pequena função de shell que itera sobre a variável PATH .

which-directory () (
  IFS=:
  set -g
  for d in $PATH; do
    if [ -z "$d" ]; then d=.; fi
    if [ -x "$d/$1" ]; then printf '%s\n' "$d"; return; fi
  done
  return 1
)

Como alternativa, você pode chamar command -v . Isso informa aliases e funções, bem como comandos externos. Caso você tenha um alias ou função mysql que chame o comando externo do mesmo nome com parâmetros adicionais, você pode chamar command -v em um shell recém-iniciado que não possui nenhuma função ou alias definido. Observe que isso faz a coisa certa somente se o alias ou função chama o comando externo do mesmo nome. Os dois one-liners a seguir são equivalentes (supondo que você não tenha nenhum nome de arquivo de diretório ou executável em seu PATH contendo uma nova linha).

dirname -- "$(sh -c 'command -v "$0"' -- mysql)"
sh -c 'command -v "$0"' -- mysql | sed -e 's!.*/!!'

No zsh, esse one-liner faz a mesma coisa:

echo =mysql(:h)
    
por 02.08.2013 / 02:35

Tags