Ao olhar para o caminho para um executável ou verificar o que aconteceria se você inserir um nome de comando em um shell Unix, há uma infinidade de utilidades diferentes ( which
, type
, command
, whence
, where
, whereis
, whatis
, hash
, etc).
Muitas vezes ouvimos que isso which
deve ser evitado. Por quê? O que devemos usar em vez disso?
shell
history
which
portability
Stéphane Chazelas
fonte
fonte
which
está assumindo um contexto de shell interativo. Esta pergunta está marcada / portabilidade. Então, eu interpreto a pergunta neste contexto como "o que usar em vez dewhich
encontrar o primeiro executável de um determinado nome no$PATH
". A maioria das respostas e razões contrawhich
lidar com aliases, buildins e funções, que na maioria dos scripts de shell portáteis do mundo real são apenas de interesse acadêmico. Aliases definidos localmente não são herdados ao executar um script de shell (a menos que você o forneça.
).csh
(ewhich
ainda é umcsh
script na maioria dos Unices comerciais) é lido~/.cshrc
quando não interativo. É por isso que você notará que os scripts csh geralmente começam#! /bin/csh -f
.which
não porque pretende fornecer os aliases, porque é uma ferramenta para usuários (interativos) decsh
. Usuários de shells POSIX possuemcommand -v
.(t)csh
(ou você não se importe se ele não fornecer o resultado correto), usetype
ou emcommand -v
vez disso . Veja as respostas para o porquê .stat $(which ls)
está errado por vários motivos (falta--
, falta de aspas), não apenas o uso dewhich
). Você usariastat -- "$(command -v ls)"
. Isso pressupõe, dels
fato, um comando encontrado no sistema de arquivos (não um componente do seu shell ou função de alias).which
pode dar-lhe o caminho errado (não o caminho que o seu shell seria executado se você entrouls
) ou dar-lhe um alias, conforme definido na configuração de alguns outros conchas ...which
implementações não forneceriam a você ols
que seria encontrado por uma pesquisa$PATH
(independentemente do quels
possa ser chamado no seu shell).sh -c 'command -v ls'
, ouzsh -c 'rpm -q --whatprovides =ls'
são mais propensos a fornecer a resposta correta. O ponto aqui é quewhich
é uma herança quebrada decsh
.Respostas:
Aqui está tudo o que você nunca pensou que nunca iria querer saber sobre isso:
Sumário
Para obter o nome do caminho de um executável em um script de shell semelhante ao Bourne (existem algumas ressalvas; veja abaixo):
Para descobrir se um determinado comando existe:
No prompt de um shell interativo tipo Bourne:
O
which
comando é uma herança quebrada do C-Shell e é melhor ficar sozinho em conchas semelhantes a Bourne.Casos de Uso
Há uma distinção entre procurar essas informações como parte de um script ou interativamente no prompt do shell.
No prompt do shell, o caso de uso típico é: esse comando se comporta de maneira estranha, estou usando o correto? O que exatamente aconteceu quando eu digitei
mycmd
? Posso olhar mais para o que é?Nesse caso, você deseja saber o que seu shell faz quando invoca o comando sem realmente invocá-lo.
Nos scripts shell, ele tende a ser bem diferente. Em um script de shell, não há razão para você querer saber onde ou qual é o comando, se tudo o que você quer fazer é executá-lo. Geralmente, o que você deseja saber é o caminho do executável, para que você possa obter mais informações (como o caminho para outro arquivo relativo a ele ou ler informações do conteúdo do arquivo executável nesse caminho).
Interativamente, você pode querer saber sobre todos os
my-cmd
comandos disponíveis no sistema, em scripts, raramente.A maioria das ferramentas disponíveis (como costuma ser o caso) foram projetadas para serem usadas interativamente.
História
Um pouco da história primeiro.
O início do shell do Unix até o final dos anos 70 não tinha funções ou pseudônimos. Somente a procura tradicional de executáveis em
$PATH
.csh
introduziu aliases por volta de 1978 (embora tenhacsh
sido lançado pela primeira vez em2BSD
maio de 1979), e também o processamento de um.cshrc
para os usuários personalizarem o shell (todo shell, como secsh
lê.cshrc
mesmo quando não é interativo, como nos scripts).enquanto o shell Bourne foi lançado pela primeira vez no Unix V7 no início de 1979, o suporte a funções só foi adicionado muito mais tarde (1984 no SVR2) e, de qualquer forma, ele nunca teve algum
rc
arquivo (.profile
é para configurar seu ambiente, não o shell em si ).csh
ficou muito mais popular que o shell Bourne porque (embora tivesse uma sintaxe muito pior que o shell Bourne), estava adicionando muitos recursos mais convenientes e agradáveis para uso interativo.Em
3BSD
(1980), umwhich
script csh foi adicionado para que oscsh
usuários ajudassem a identificar um executável, e é um script dificilmente diferente que você pode encontrar hojewhich
em muitos Unices comerciais (como Solaris, HP / UX, AIX ou Tru64).Esse script lê o usuário
~/.cshrc
(como todos oscsh
scripts fazem, a menos que seja invocado comcsh -f
) e consulta os nomes de comando fornecidos na lista de aliases e em$path
(a matrizcsh
mantida com base em$PATH
).Aqui está,
which
primeiro lugar para o shell mais popular da época (ecsh
ainda era popular até meados dos anos 90), que é a principal razão pela qual foi documentado em livros e ainda é amplamente utilizado.Observe que, mesmo para um
csh
usuário, essewhich
script csh não fornece necessariamente as informações corretas. Ele obtém os aliases definidos em~/.cshrc
, não os que você pode ter definido mais tarde no prompt ou, por exemplo,source
inserindo outrocsh
arquivo e (embora isso não seja uma boa idéia),PATH
possa ser redefinido~/.cshrc
.A execução desse
which
comando a partir de um shell Bourne ainda procuraria aliases definidos em seu diretório~/.cshrc
, mas se não houver um porque você não o usacsh
, provavelmente ainda obterá a resposta certa.Uma funcionalidade semelhante não foi adicionada ao shell Bourne até 1984 no SVR2 com o
type
comando embutido. O fato de ele estar embutido (em oposição a um script externo) significa que ele pode fornecer as informações corretas (até certo ponto), pois ele tem acesso aos elementos internos do shell.O
type
comando inicial sofreu um problema semelhante ao dowhich
script, pois não retornou um status de saída com falha se o comando não foi encontrado. Além disso, para os executáveis, ao contráriowhich
, ele gera algo como, emls is /bin/ls
vez de apenas o/bin/ls
que tornou menos fácil o uso em scripts.O shell Bourne da versão 8 do Unix (não lançado na natureza) tinha o
type
nome incorporadowhatis
. E o shell do Plan9 (o futuro sucessor do Unix)rc
(e seus derivados comoakanga
ees
) também temwhatis
.O shell Korn (um subconjunto no qual a definição sh POSIX se baseia), desenvolvido em meados dos anos 80, mas não amplamente disponível antes de 1988, adicionou muitos dos
csh
recursos (editor de linha, aliases ...) no topo do shell Bourne . Ele adicionou seu própriowhence
builtin (além detype
), que tomou várias opções (-v
para fornecer atype
saída detalhada semelhante a, e-p
procurar apenas executáveis (não aliases / funções ...)).Coincidentemente à turbulência com relação às questões de direitos autorais entre a AT&T e Berkeley, algumas implementações de shell de software livre surgiram no final dos anos 80 e início dos 90. Todo o shell Almquist (ash, para substituir o shell Bourne nos BSDs), a implementação de domínio público do ksh (pdksh)
bash
(patrocinada pela FSF),zsh
foi lançada entre 1989 e 1991.Ash, apesar de ser um substituto para o shell Bourne, não tinha um
type
built-in até muito mais tarde (no NetBSD 1.3 e no FreeBSD 2.3), embora tivessehash -v
. O OSF / 1/bin/sh
tinha umtype
built-in que sempre retornava 0 até OSF / 1 v3.x.bash
nãowhence
adicionou uma-p
opção, mas adicionou uma opção paratype
imprimir o caminho (type -p
seria comowhence -p
) e-a
relatar todos os comandos correspondentes.tcsh
fezwhich
builtin e adicionou umwhere
comando agindo comobash
'stype -a
.zsh
tem todos eles.O
fish
shell (2005) possui umtype
comando implementado como uma função.O
which
roteiro csh entretanto foi removido do NetBSD (como era embutido no tcsh e de não muito uso em outras conchas), e a funcionalidade adicional parawhereis
(quando invocado comowhich
,whereis
se comporta comowhich
exceto que ele só olha para cima executáveis em$PATH
). No OpenBSD e no FreeBSD,which
também foi alterado para um escrito em C que consulta$PATH
apenas os comandos .Implementações
Existem dezenas de implementações de um
which
comando em vários Unices com sintaxe e comportamento diferentes.No Linux (além dos integrados no
tcsh
ezsh
), encontramos várias implementações. Nos sistemas Debian recentes, por exemplo, é um simples shell script POSIX que procura por comandos$PATH
.busybox
também tem umwhich
comandoHá uma
GNU
which
que é provavelmente a mais extravagante. Ele tenta estender o que owhich
script csh fez a outros shells: você pode dizer quais são seus apelidos e funções para que ele possa lhe dar uma resposta melhor (e acredito que algumas distribuições Linux definem alguns apelidos globais em torno disso parabash
fazer isso) .zsh
possui alguns operadores para expandir para o caminho dos executáveis: o operador de=
expansão de nome de arquivo e o:c
modificador de expansão de histórico (aqui aplicado à expansão de parâmetro ):zsh
, nozsh/parameters
módulo também cria a tabela de hash do comando como acommands
matriz associativa:O
whatis
utilitário (exceto aquele no shell Unix V8 Bourne ou no Plan 9rc
/es
) não é realmente relacionado, pois é apenas para documentação (mostra o banco de dados whatis, que é a sinopse da página de manual).whereis
também foi adicionado3BSD
ao mesmo tempo emwhich
que foi gravado eC
nãocsh
é usado para procurar ao mesmo tempo o executável, a página de manual e a fonte, mas não com base no ambiente atual. Então, novamente, isso responde a uma necessidade diferente.Agora, na frente padrão, o POSIX especifica os comandos
command -v
e-V
(que eram opcionais até o POSIX.2008). UNIX especifica otype
comando (sem opção). Isso é tudo (where
,which
,whence
não são especificados em qualquer padrão)Até algumas versões,
type
ecommand -v
eram opcionais na especificação Linux Standard Base, o que explica por que, por exemplo, algumas versões antigasposh
(embora baseadas naspdksh
que tinham as duas) também não tinham.command -v
também foi adicionado a algumas implementações de shell Bourne (como no Solaris).Status Hoje
Atualmente, o status é esse
type
ecommand -v
é onipresente em todas as conchas do tipo Bourne (embora, como observado por @jarno, observe a advertência / bugbash
quando não estiver no modo POSIX ou alguns descendentes do shell Almquist abaixo nos comentários).tcsh
é o único shell em que você gostaria de usarwhich
(como nãotype
existe ewhich
está embutido).Nos outros do que conchas
tcsh
ezsh
,which
pode dizer-lhe o caminho do executável dado enquanto não há nenhuma alias ou função por esse mesmo nome em qualquer um dos nossos~/.cshrc
,~/.bashrc
ou qualquer arquivo de inicialização shell e você não definir$PATH
a sua~/.cshrc
. Se você tiver um alias ou função definido para ele, ele pode ou não falar sobre isso ou dizer a coisa errada.Se você quiser saber sobre todos os comandos com um determinado nome, não há nada portátil. Você usaria
where
emtcsh
ouzsh
,type -a
nabash
ouzsh
,whence -a
no ksh93 e em outros shells, você pode usartype
em combinação comwhich -a
o que pode trabalhar.Recomendações
Obtendo o nome do caminho para um executável
Agora, para obter o nome do caminho de um executável em um script, existem algumas ressalvas:
seria a maneira padrão de fazê-lo.
Existem alguns problemas, porém:
type
,which
,command -v
... todas as heurísticas de uso para descobrir o caminho. Eles percorrem os$PATH
componentes e localizam o primeiro arquivo que não é de diretório para o qual você tem permissão de execução. No entanto, dependendo do shell, quando se trata de executar o comando, muitos deles (Bourne, AT&T ksh, zsh, ash ...) apenas os executam na ordem de$PATH
até que aexecve
chamada do sistema não retorne com erro . Por exemplo, se$PATH
contém/foo:/bar
e você deseja executarls
, eles primeiro tentarão executar/foo/ls
ou se isso falhar/bar/ls
. Agora execução de/foo/ls
pode falhar porque você não tem permissão de execução, mas também por muitos outros motivos, como se não fosse um executável válido.command -v ls
informaria/foo/ls
se você tiver permissão de execução/foo/ls
, mas a execuçãols
pode realmente ser executada/bar/ls
se/foo/ls
não for um executável válido.foo
é um builtin ou função ou alias,command -v foo
retornafoo
. Com alguns shells comoash
,pdksh
ouzsh
, ele também pode retornarfoo
se$PATH
incluir a string vazia e houver umfoo
arquivo executável no diretório atual. Existem algumas circunstâncias em que você pode levar isso em consideração. Lembre-se, por exemplo, de que a lista de componentes internos varia com a implementação do shell (por exemplo,mount
às vezes é incorporada ao busyboxsh
) e, por exemplo,bash
pode obter funções do ambiente.$PATH
contiver componentes de caminho relativo (normalmente.
ou a cadeia vazia que se refere ao diretório atual, mas pode ser qualquer coisa), dependendo do shell,command -v cmd
pode não gerar um caminho absoluto. Portanto, o caminho que você obtém no momento da execuçãocommand -v
não será mais válido depois de vocêcd
em outro lugar./opt/ast/bin
(embora esse caminho exato pode variar em diferentes sistemas creio eu) está em você$PATH
, ksh93 vai disponibilizar algumas builtins extras (chmod
,cmp
,cat
...), mascommand -v chmod
vai voltar/opt/ast/bin/chmod
mesmo se esse caminho doesn' não existe.Determinando se um Comando Existe
Para descobrir se um determinado comando existe de maneira padrão, você pode:
Onde alguém pode querer usar
which
(t)csh
Em
csh
etcsh
você não tem muita escolha. Emtcsh
, tudo bem comowhich
está embutido. Emcsh
, esse será owhich
comando do sistema , que pode não fazer o que você deseja em alguns casos.encontre comandos apenas em algumas conchas
Um caso em que pode fazer sentido usar
which
é se você quer saber o caminho de um comando, ignorando builtins shell potenciais ou funções embash
,csh
(nãotcsh
),dash
ouBourne
shell scripts que é conchas que não têmwhence -p
(comoksh
ouzsh
) ,command -ev
(likeyash
),whatis -p
(rc
,akanga
) ou um builtinwhich
(liketcsh
ouzsh
) em sistemas ondewhich
está disponível e não é ocsh
script.Se essas condições forem atendidas, então:
forneceria o caminho do primeiro
echo
em$PATH
(exceto nos casos de canto), independentemente de serecho
também um shell builtin / alias / function ou não.Em outras conchas, você prefere:
echo==echo
ouecho=$commands[echo]
ouecho=${${:-echo}:c}
echo=$(whence -p echo)
echo=$(command -ev echo)
echo=`whatis -p echo`
(cuidado com os caminhos com espaços)set echo (type -fp echo)
Observe que, se tudo o que você quer fazer é executar esse
echo
comando, você não precisa obter o caminho, basta:Por exemplo, com
tcsh
, para impedir que o builtinwhich
seja usado:quando você precisa de um comando externo
Outro caso em que você pode querer usar
which
é quando você realmente precisa de um comando externo. O POSIX exige que todos os recursos internos do shell (comocommand
) também estejam disponíveis como comandos externos, mas infelizmente esse não é o casocommand
em muitos sistemas. Por exemplo, é raro encontrar umcommand
comando em sistemas operacionais baseados em Linux, enquanto a maioria deles possui umwhich
comando (embora diferentes, com opções e comportamentos diferentes).Os casos em que você pode querer um comando externo estão onde quer que você execute um comando sem chamar um shell POSIX.
As funções
system("some command line")
,popen()
... do C ou de vários idiomas chamam um shell para analisar essa linha de comando, assimsystem("command -v my-cmd")
como o trabalho neles. Uma exceção a isso seriaperl
otimizar o shell se ele não vir nenhum caractere especial do shell (além do espaço). Isso também se aplica ao seu operador de backtick:A adição disso
:;
acima forçaperl
a invocar uma concha lá. Ao usarwhich
, você não precisaria usar esse truque.fonte
which
é umcsh
script em muitos escritórios comerciais. O motivo é histórico, foi por isso que dei a história, para que as pessoas entendam de onde ela veio, por que as pessoas se acostumaram a usá-lo e por que, na verdade, não há motivo para você usá-lo. E sim, algumas pessoas usam (t) csh. Nem todo mundo usa Linux aindawhich
, em oposição às coisas que você está tentando usarwhich
, o histórico dewhich
, implementações dewhich
outros comandos para executar tarefas relacionadas ou razões para usá-lowhich
? Por que os outros comandos são melhores ? Do que eles fazem diferentewhich
? Como eles evitam suas armadilhas? Esta resposta realmente gasta mais palavras nos problemas com as alternativas do que com os problemaswhich
.command -v
não verifica a permissão de execução, pelo menos se você a chamar pelo argumento de nome de arquivo puro sem caminho. Eu testei pelo traço 0.5.8 e GNU bash 4.3.48.touch /usr/bin/mytestfile
e depois executá-command -v mytestfile
lo, ele fornecerá o caminho (enquantowhich mytestfile
que não).bash
se instalará em um arquivo não executável se não puder encontrar um executável, por isso está "OK" (embora na prática prefiracommand -v
/type
retorne um erro), pois esse é o comando que ele tentaria executar quando você executarmytestfile
, mas odash
o comportamento é incorreto, como se houvesse um não executávelcmd
à frente de um executável,command -v
retornasse o não executável enquanto a execuçãocmd
executaria o executável (o errado também é hash). O FreeBSDsh
(também baseado emash
) possui o mesmo bug. zsh, yash, ksh, mksh, bash como sh estão OK.As razões pelas quais alguém pode não querer usar
which
já foram explicadas, mas aqui estão alguns exemplos em alguns sistemas em quewhich
realmente falha.Em shells semelhantes a Bourne, estamos comparando a saída
which
com a saída detype
(type
sendo um shell incorporado, deve ser a verdade básica, pois é o shell nos dizendo como chamaria um comando).Muitos casos são de canto , mas lembre-se de que
which
/type
são freqüentemente usados em casos de canto (para encontrar a resposta para um comportamento inesperado como: por que diabos esse comando está se comportando assim, para quem eu estou chamando? ).A maioria dos sistemas, a maioria das cascas tipo Bourne: funções
O caso mais óbvio é para funções:
O motivo é que
which
apenas relatórios sobre executáveis e, às vezes, sobre aliases (embora nem sempre sejam os do seu shell), não funcionam.O GNU cuja página de manual possui um exemplo quebrado (como eles se esqueceram de citar
$@
) de como usá-lo para reportar funções também, mas assim como para aliases, porque não implementa um analisador de sintaxe de shell, é facilmente enganado:A maioria dos sistemas, a maioria dos invólucros Bourne: builtins
Outro caso óbvio é builtins ou palavras-chave, como
which
sendo um comando externo não tem nenhuma maneira de saber qual builtins sua concha tem (e alguns escudos comozsh
,bash
ouksh
pode carregar builtins dinamicamente):(que não se aplica a
zsh
ondewhich
está embutido)Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5.1 e muitos outros:
Isso ocorre porque na maioria dos Unices comerciais
which
(como na implementação original no 3BSD) é umcsh
script que lê~/.cshrc
. Os aliases que serão relatados são os definidos lá, independentemente dos aliases que você definiu atualmente e independentemente do shell que você está realmente usando.No HP / UX ou Tru64:
(as versões Solaris e AIX corrigiram esse problema salvando
$path
antes de ler~/.cshrc
e restaurando antes de procurar o (s) comando (s))Ou:
(é claro, sendo um
csh
script, você não pode esperar que funcione com argumentos que contenham espaços ...)CentOS 6.4, bash
Nesse sistema, existe um apelido definido em todo o sistema que agrupa o
which
comando GNU .A saída falsa é porque
which
lê a saída dobash
'salias
, mas não sabe como analisar corretamente e usa heurísticas (um apelido por linha, procura o primeiro encontrado comando depois de um|
,;
,&
...)A pior coisa do CentOS é que ele
zsh
possui umwhich
comando interno perfeitamente bem, mas o CentOS conseguiu quebrá-lo, substituindo-o por um alias que não funcionava no GNUwhich
.Debian 7.0, ksh93:
(embora se aplique à maioria dos sistemas com muitos shells)
No Debian,
/bin/which
é um/bin/sh
script. No meu caso,sh
ser ,dash
mas é o mesmo quando ébash
.Um unset
PATH
não é para desativarPATH
a pesquisa, mas significa utilizar do sistema PATH padrão que, infelizmente, no Debian, ninguém concorda com (dash
ebash
tem/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
,zsh
tem/bin:/usr/bin:/usr/ucb:/usr/local/bin
,ksh93
tem/bin:/usr/bin
,mksh
tem/usr/bin:/bin
($(getconf PATH)
),execvp()
(como emenv
) tem:/bin:/usr/bin
(sim, procura no diretório atual primeiro! )).É por isso que
which
deixa ele errada acima, uma vez que está usandodash
's padrãoPATH
que é diferente deksh93
' sNão é melhor com o GNU
which
que relata:(curiosamente, existe realmente um
/usr/local/bin/which
no meu sistema que é realmente umakanga
script que acompanhaakanga
(umrc
derivado do shell em que o padrãoPATH
é/usr/ucb:/usr/bin:/bin:.
))bash, qualquer sistema:
Aquele a quem Chris está se referindo em sua resposta :
Também depois de ligar
hash
manualmente:Agora, um caso em que,
which
às vezes,type
falha:Agora, com algumas conchas:
Com outros:
Nem
which
nemtype
pode saber de antemão queb/foo
não pode ser executado. Algumas conchas comobash
,ksh
ouyash
, ao invocarfoo
vai realmente tentar executarb/foo
e relatar um erro, enquanto outros (comozsh
,ash
,csh
,Bourne
,tcsh
) será executadoa/foo
após o fracasso daexecve()
chamada de sistema onb/foo
.fonte
mksh
na verdade, usa algo diferente para o padrão$PATH
: primeiro, a constante em tempo de compilação do sistema operacional_PATH_DEFPATH
é usada (geralmente nos BSDs), depoisconfstr(_CS_PATH, …)
é usada (POSIX) e, se ambas não existirem ou falharem,/bin:/usr/bin:/sbin:/usr/sbin
será usada.ls
seja uma função que está sendo usadals
no PATH. Ewhich
é bom dizer qual é o usado/usr/bin/ls
ou/usr/local/bin/ls
. Eu não vejo "Por que não usar que" ....which ls
vai me dar,/bin/ls
independentemente de als
função chamar/bin/ls
ou/opt/gnu/bin/ls
oudir
ou nada. IOW,which
(aquela que implementações, IMMV) está dando algo irrelevantels
é uma função. Eu sei que minhals
função está chamandols
dePATH
. Agorawhich
me diz onde está o arquivo. Você vê apenas um único caso de uso: "O que meu shell faria com este comando". Para este caso de usowhich
está errado, correto. Mas há outros casos de uso em que (GNU)which
é exatamente a coisa certa.which
implementação. Alguns dirão que é um apelido (se você tiver um apelido configurado ou se houver um apelido~/.cshrc
em sua casa que possua esse apelido), outros darão um caminho, mas o caminho errado, sob algumas condições.sh -c 'command -v ls'
, embora não seja perfeito, é mais provável que você dê a resposta certa para esse requisito diferente (e também é padrão).Uma coisa que (pela minha rápida olhada) parece que Stephane não mencionou é que
which
não tem idéia da tabela de hash do caminho do seu shell. Isso tem o efeito de retornar um resultado que não é representativo do que realmente é executado, o que o torna ineficaz na depuração.fonte
No espírito do UNIX: Faça com que cada programa faça uma coisa bem.
Se o objetivo é responder: Qual executável existe com esse nome?
O programa executável fornecido com os sistemas Debian é uma boa resposta. O que forneceu o csh incluía aliases, que é uma fonte de problemas. O que algumas conchas fornecem como um interno interno tem um objetivo diferente. Use esse executável ou use o script fornecido no final desta resposta.
Se esse script for usado, o que ele responde é limpo, simples e útil.
Este objetivo corresponderá à primeira frase da sua pergunta:
Se você possui um sistema que não possui um executável chamado, o qual (a maioria dos sistemas Linux possui um), você pode criar um
~/bin/which
anteriormente/bin/
no PATH, para que os executáveis pessoais substituam os do sistema como o da parte inferior deste post:Esse executável listará (por padrão) todos os executáveis encontrados no PATH. Se apenas o primeiro for necessário, a opção
-f
estará disponível.Nesse ponto, caímos em um objetivo diferente:
o que o shell executará (após a análise)
Isso vem da sua segunda frase:
Este segundo assunto tenta encontrar uma boa resposta para uma pergunta que é bastante difícil de responder. Os reservatórios têm visões divergentes, caixas de canto e (no mínimo) interpretações diferentes. Adicionando a isso:
E claro, todas as tentativas correspondem a esse objetivo.
Evitar qual?
Eu me pergunto: Por que isso deveria ser dito se
which
funciona bem (pelo menos no debian)?No espírito do UNIX: Faça com que cada programa faça uma coisa bem.
O programa externo
which
está fazendo uma coisa: Encontre o primeiro executável no PATH que tenha o mesmo nome que o nome do comando . E está fazendo isso razoavelmente bem.Não conheço nenhum outro programa ou utilitário que responda a essa pergunta de uma maneira mais fundamental. Como tal, é útil e pode ser usado quando necessário.
A alternativa mais próxima parece ser
command -pv commandName
:, mas isso também informará sobre buildins e aliases. Não é a mesma resposta.Claro,
which
é limitado, não responde a todas as perguntas, nenhuma ferramenta poderia fazer isso (bem, ainda não ...). Mas é útil quando usado para responder à pergunta que foi projetada para responder (a logo acima). Muito parecidoed
foi limitado e depoissed
apareceu (ouvi
/vim
). Ou comoawk
foi limitado e fez Perl aparecer e estender. No entanto,ed
,sed
e / ouawk
tem casos de uso específicos ondevim
ouperl
são não as melhores ferramentas.Provavelmente porque
which
responde apenas a uma parte da pergunta que um usuário de shell pode fazer:O que está sendo executado quando eu digito um commandName?
Externo que
Que deve estar disponível (em muitos sistemas) como um executável externo.
A única maneira de chamar essa ferramenta externa é usar env para sair do shell e depois chamar
which
(que funciona em todos os shells):Ou use o caminho completo para
which
(que pode variar em diferentes sistemas):Por que isso é
hack
necessário? Como algumas conchas (especialmente zsh) ocultamwhich
:Ser uma ferramenta externa (como
env
) explica perfeitamente por que não reportará informações internas do shell. Como aliases, funções, builtins, builtins especiais, variáveis de shell (não exportadas), etc:A saída vazia de
ll
(um alias comum parall='ls -l'
) indica quell
não está relacionado a um programa executável ou, pelo menos, que não há nenhum arquivo executável nomeadoll
no PATH. O uso dell
deve chamar outra coisa, neste caso, um alias:type
ecommand
Os comandos
type
ecommand -v
são solicitados pelo POSIX. Espera-se que eles trabalhem na maioria das conchas, e funcionam, exceto em csh, tcsh, fish e rc.Ambos os comandos podem ser usados para fornecer outro ponto de vista sobre o qual o comando será executado.
whence
,where
,whereis
,whatis
,hash
Então, há
whence
,where
,whereis
,whatis
,hash
, e alguns outros. Todas as respostas diferentes para perguntas semelhantes. Todos funcionam de maneiras diferentes em conchas diferentes. Provavelmente,whence
é o mais comum depoistype
. Os outros são soluções especiais que respondem à mesma pergunta de maneiras diferentes.Provavelmente
which
primeiro a saber se existe um executável com o nome do commandName , em seguida,type
ecommand
em seguida, se o commandName não foi encontrado ainda:whence
,where
,whereis
,whatis
,hash
nessa ordem.Script de shell para fornecer um
which
executável.fonte
Eu nunca tinha ouvido aquilo. Forneça exemplos específicos. Eu me preocuparia com sua distribuição Linux e pacotes de software instalados, pois é daí que
which
vem!SLES 11.4 x86-64
na versão tcsh 6.18.01:
na versão bash 3.2-147:
which
faz parte do util-linux, um pacote padrão distribuído pela Linux Kernel Organization para uso como parte do sistema operacional Linux. Ele também fornece esses outros arquivosmy
util-linux
é a versão 2.19. As notas de versão podem ser facilmente encontradas na v2.13 de 28 de agosto de 2007. Não tendo certeza de qual era o objetivo ou objetivo disso, certamente não foi respondido naquela coisa demorada, votada 331 vezes.fonte
which -v
mostra, esse é o GNU que (o extravagante mencionado na outra resposta e não é de forma alguma específico para o Linux), não o util-linux que o AFAIK nunca incluiu umwhich
utilitário. util-linux 2.19 é de 2011, GNU que 2.19 é de 2008.