Eu criei um programa C simples assim:
int main(int argc, char *argv[]) {
if (argc != 5) {
fputs("Not enough arguments!\n", stderr);
exit(EXIT_FAILURE);
}
E eu tenho meu PATH modificado no etc / bash.bashrc da seguinte forma:
PATH=.:$PATH
Salvei este programa como set.c e estou compilando-o com
gcc -o set set.c
na pasta
~/Programming/so
No entanto, quando ligo
set 2 3
nada acontece. Não há texto que apareça.
Chamando
./set 2 3
dá o resultado esperado
Eu nunca tive um problema com PATH antes e
which set
retorna ./set
. Parece que o CAMINHO é o correto. O que está acontecendo?
shell
path
shell-builtin
Ganea Dan Andrei
fonte
fonte
test
basicamente pelo mesmo motivo;test
também é um shell embutido.test
parece fazer sentido. É claro que, no momento em que você o coloca,PATH
você deve ter um nome diferente. E até você colocar o programa no seu,PATH
você teria que invocá-lo da mesma./test
maneira. Portanto, é bom usar o nometest
de um programa, desde que seja um teste rápido que você deseja excluir antes do final do dia.foo
.ls
sempre que for ver se ele existe, ele será executado (mas somente se você modificar seu caminho, como fez na pergunta).Respostas:
Em vez de usar
which
, que não funciona quando você mais precisa , usetype
para determinar o que será executado quando você digitar um comando:O shell sempre procura por componentes internos antes de pesquisar no
$PATH
, portanto, a configuração$PATH
não ajuda aqui.Seria melhor renomear seu executável para outra coisa, mas se sua atribuição exigir que o programa seja nomeado
set
, você poderá usar uma função de shell:(Isso funciona
bash
, mas outros shellsksh
podem não permitir. Consulte a resposta do mikeserv para obter uma solução mais portátil.)Agora, a digitação
set
executará a função denominada "set", que é executada./set
. O GNUbash
procura funções antes de procurar por componentes internos e procura por componentes internos antes de pesquisar no$PATH
. A seção chamada "COMMAND EXECUTION" na página de manual do bash fornece mais informações sobre isso.Consulte também a documentação sobre
builtin
ecommand
:help builtin
ehelp command
.fonte
type
maiswhich
, mas não dão qualquer motivo. ( Eu sei porque , mas alguém que precisa a recomendação não faria.)type
vez dewhich
, não nomeie seu programa como "definido" e perceba quefunction set { ./set; }
é um truque feio que você provavelmente deve evitar.set
é um builtin no bash (e provavelmente na maioria das outras conchas). Isso significa que o bash nem pesquisará o caminho ao procurar a função.Como observação lateral, eu recomendaria fortemente que não aumentasse
.
o caminho por razões de segurança. Imagine, por exemplo,cd
sair/tmp
após qualquer outro usuário adicionar um arquivo executável/tmp/cd
.fonte
cd
é um shell interno, portanto, o exemplo não funcionará pelo mesmo motivo que comset
../foo
para invocar um programa é profissional; mostra que você entende por.
que não deve estar em $ PATH. Seu professor está errado, e você pode dizer a ele que eu disse isso.set
não é apenas um embutido, é um embutido especial do POSIX . Existem alguns comandos internos que são padrões especificados para serem encontrados em uma pesquisa de comandos antes de qualquer outra coisa -$PATH
não são pesquisados, nomes de funções não são pesquisados etc. A maioria dos componentes internos que não são especiais são realmente exigidos pelo padrão POSIX encontrado$PATH
antes de o shell executar qualquer um de seus próprios procedimentos internos. Isto é verdade paraecho
e a maioria dos outros (embora se a norma é honrado a este respeito tem sido um assunto de discórdia nas listas de discussão do grupo aberto no passado) , mas não deset
,trap
,break
,return
,continue
,.
,:
,times
,eval
,exit
,export
,readonly
,unset
, Ouexec
.Todos esses são nomes reservados do shell e possuem atributos especiais além da ordem de preferência para a pesquisa de comandos. Por exemplo, você não pode definir uma função de shell com nenhum desses nomes em um shell compatível com os padrões. Isso é bom - permite que as pessoas escrevam scripts portáteis com segurança . Esses são comandos de linha de base a partir dos quais um escritor de scripts experiente pode estabelecer uma base segura e confiável em seu ambiente. Invadir esse espaço para nome não é aconselhável.
No entanto, se você deseja invadi-lo, pode fazê-lo de maneira portável
alias
. A ordem da expansão do shell permite essa solução alternativa. Como oalias
é expandido enquanto o comando está sendo lido, o que quer que você substitua oset
nome na sua definição será expandido corretamente, provavelmente não deve ser expandido para um desses nomes.Então você poderia fazer:
... o que vai funcionar muito bem.
fonte
O problema é que
set
é um shell embutido e a melhor solução seria usar um nome diferente para o seu programa executável.Aliás, na semana passada, fiz uma pergunta sobre como executar comandos do sistema em vez de shell builtins com o mesmo nome e a solução que aceitei foi executar o comando através de
env
:Nesse caso específico, onde você já sabe que o comando que deseja usar está localizado no diretório atual, seria melhor executar diretamente o executável digitando seu caminho (usando
.
para representar o diretório de trabalho atual):As duas soluções acima são independentes de shell, ou seja, elas funcionarão independentemente do shell que você estiver usando.
Sugestões como o uso do
command
builtin não funcionarão no Bash: isso apenas impede a execução de funções do shell . Embora não esteja documentado, também notei que o usocommand
também suprime as palavras-chave do shell . No entanto, ele não fará o mesmo para os shell embutidos , comoset
. Pelo que entendi,command
pode funcionar com outros shells, como o zsh.Além disso, truques, como
\set
ou"set"
ou'set'
não fazer o trabalho para builtins Bash - embora eles são úteis para a execução de arquivos executáveis em vez de aliases ou shell palavras-chave .Nota: Esta resposta começou originalmente como um comentário na resposta de Eric (aceita), mas cresceu muito para caber em um comentário. As outras respostas recomendando o uso
type
e não adicionando.
ao PATH são boas.fonte