Por que preciso digitar `. /` Antes de executar um programa no diretório atual?

92

Ao executar um programa C a.out, usando o terminal Ubuntu, por que eu sempre preciso digitar ./antes a.out, em vez de apenas escrever a.out? Existe solução para isso?

Prashant Chikhalkar
fonte

Respostas:

119

Quando você digita o nome de um programa, como a.outo sistema, procura o arquivo no seu PATH. No meu sistema, PATH está definido como

/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

O seu provavelmente é semelhante. Para verificar, entre echo $PATHem um terminal.

O sistema examina esses diretórios na ordem indicada e, se não conseguir encontrar, o programa produz um command not founderro.

Anexar o comando com ./efetivamente diz "esqueça o PATH, quero que você procure apenas no diretório atual".

Da mesma forma, você pode dizer ao sistema para procurar apenas em outro local específico, acrescentando o comando a um caminho relativo ou absoluto, como:

../significa no diretório pai, por exemplo, ../helloprocure hello no diretório pai.

./Debug/hello: "procure hellono subdiretório Debug do meu diretório atual."

ou /bin/ls: "procure lsno diretório /bin"

Por padrão, o diretório atual não está no caminho porque é considerado um risco de segurança. Veja Por que é. não está no caminho por padrão? no Superusuário por que.

É possível adicionar o diretório atual ao seu PATH, mas pelos motivos apresentados na pergunta vinculada, eu não o recomendaria.

Warren Hill
fonte
25
Este. +1 Não adicionar .ao seu PATH(como os outros 2 respostas atualmente sugerem), devido ao risco de segurança mencionados nesta resposta.
Dia
8
Também pode ser interessante notar que não há nada de especial .aqui, você pode usar um caminho completo ou relativo para um executável, por exemplo, /home/user/foo/a.outou./build/a.out
tobyodavies
@tobyodavies; Na verdade, .é especial porque significa "meu diretório atual" e, portanto, qualquer diretório em que o usuário se encontre com privilégios de leitura e execução. Isso é potencialmente mais perigoso do que adicionar um caminho específico totalmente qualificado.
21713 Warren Hill
@WarrenHill ao considerar adicioná-lo ao seu caminho, sim, é bem diferente. No entanto, em termos de sintaxe do bash, .não possui status especial, é apenas um caminho que poderia começar /e ./blahfuncionaria tão bem com catou grepcomo um prompt do bash.
tobyodavies
@tobyodavies: OK. Eu editei minha resposta para incluir seu ponto.
21713 Warren Hill
24

A razão para isso é simples.

Suponha que você tenha um comando com o mesmo nome de um aplicativo no diretório atual. A execução do comando no shell chamaria seu aplicativo em vez do comando interno. Isso seria uma preocupação de segurança, se nada mais.

Ao exigir o ./uso inicial, o shell sabe que você deseja executar o aplicativo com o nome especificado e não um comando interno com esse nome.

Nathan Osman
fonte
1
Se sua explicação for enganosa, há uma diferença entre comandos internos em um shell e executáveis ​​acessíveis através da variável PATH. Por uma questão de fato, sua resposta, quanto mais eu leio, parece mais incorreta.
Ahmed Masud
16

./executa arquivos que não estão no seu $PATH, em vez disso, executa o arquivo no diretório atual (ou outro via ./home/stefano/script.sh). Agora, PATH é uma variável de ambiente que contém todos os locais onde o bash pode procurar programas executáveis, sem ter o caminho completo (absoluto) para eles.

Essa separação é necessária para evitar a execução do arquivo errado. Ou seja, se você tiver um arquivo chamado lsno diretório inicial, ele não estará no PATH impedirá que o bash o confunda com o real ls. A variável PATH também define a ordem da pesquisa:

  • Quando você executa um comando ou um programa tenta fazer um execsyscall (um método especial do Kernel, como os programas são iniciados), o sistema procura o arquivo percorrendo cada um dos diretórios do seu PATH. Depois que o programa é encontrado, mesmo que esteja em vários diretórios, a pesquisa é interrompida e o primeiro encontrado é executado.

Para executar um arquivo, você precisará definir o bit executável nas permissões:

  • Como você já está na linha de comando, basta digitar chmod +x finename.

  • Ou você pode definir as permissões clicando com o botão direito do mouse no arquivo e selecionando Propriedades :

    texto alternativo

Agora você pode copiar o arquivo para qualquer um dos diretórios no PATH, para ver quais estão lá - e eles são definidos por usuário - echo $PATH.

stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Se você criar um arquivo executável cate movê-lo para /usr/local/sbin, ele será executado em vez do apropriado cat, no qual reside /bin. Você pode descobrir onde estão seus arquivos usando type cate whereis cat.

Stefano Palazzo
fonte
2
Uma coisa a ser observada: sua pergunta parece indicar que ele compilou e vinculou algo a ele gcc, que define automaticamente o bit de execução.
Nathan Osman
12

Por que você precisa digitar ./antes de executar um programa?

No terminal, sempre que você digitar o nome de um aplicativo, digamos gedit, o terminal irá procurar em alguns diretórios (predefinidos) que contêm aplicativos (os binários dos aplicativos). Os nomes desses diretórios estão contidos em uma variável chamada PATH. Você pode ver o que há nessa variável executando echo $PATH. Veja os diretórios separados por :? Esses são os diretórios que o terminal vão pesquisar, se você acabou de digitar gedit, nautilusou a.out. Como você pode ver, o caminho do seu a.outprograma não está lá. Ao fazê-lo ./a.out, você está dizendo ao terminal "procure no diretório atual e execute a.out, e não entre PATH.

Solução 1

Se você não quiser digitar ./todas as vezes, precisará adicionar a.outo diretório $PATH. Nas instruções a seguir, assumirei que o caminho para a.outé /path/to/programs/, mas você deve alterá-lo para o caminho atual.

  1. Basta adicionar a seguinte linha ao final do arquivo ~/.pam_environment:

    PATH DEFAULT=${PATH}:/path/to/programs

    Fonte: Variáveis ​​de ambiente persistentes

  2. Efetue logout e logon novamente. Agora você poderá executar a.outsem ./nenhum diretório.

Se você tiver outros programas em outros diretórios, basta adicioná-los à linha acima. No entanto, aconselho que você tenha um diretório chamado "myPrograms", por exemplo, e coloque todos os seus programas nele.

Solução 2

Nota: mude userNamepara o nome de usuário atual do Ubuntu.

E se você tiver outros programas que deseja executar? E eles estão todos em pastas diferentes? Bem, uma solução "mais organizada" seria criar uma pasta chamada binno diretório Home e adicionar links simbólicos (atalhos) nessa pasta. Aqui está como:

  1. mkdir /home/userName/bin

    • Isso criará a pasta binno seu diretório inicial.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Isso criará um "link simbólico" (basicamente, um atalho) do seu a.outprograma em bin.
  3. Efetue logout e logon novamente. Agora você poderá executar a.outsem ./nenhum diretório.

Agora, sempre que você tiver outro programa em qualquer outro lugar, digamos que o programa b.inna sua área de trabalho, tudo o que você precisa fazer é: ln -s /home/userName/Desktop/b.in /home/userName/bine você poderá executá-lo sem ./o mesmo.

Nota: graças ao comentário de @ Joe , quando você faz backups, os links simbólicos precisam ser tratados especialmente. Por padrão, rsyncnão os processa, portanto, quando você restaura, eles não estão lá.

Alaa Ali
fonte
1
Este é um truque útil se usado com moderação. Usar muito faz com que seu sistema faça coisas que outras pessoas não esperariam. Além disso, quando você faz backups, os links simbólicos precisam ser tratados especialmente. Por padrão , o rsync não os processa, portanto, quando você restaura, eles não estão lá.
21413 Joe
1

Como George apontou em sua resposta, isso ajuda você a observar que você está executando um arquivo no diretório de trabalho atual ( pwd).

Lembro-me de fazer essa pergunta ao meu veterano há muito tempo, ele disse que eu deveria adicionar .ao meu caminho para que, quando o fizer a.out, procure no diretório atual e o execute. Nesse caso, não preciso fazer ./a.out.

Mas, pessoalmente, eu recomendaria contra isso. Isso nunca aconteceu comigo, mas se você estiver em um diretório de rede alienígena ou algo assim, e um arquivo executável malicioso chamado lsexistir lá, ter .no seu caminho é uma péssima idéia. Não que você encontre esse problema com muita frequência, apenas dizendo.

Shrikant Sharat
fonte
ok, Stefano adotou sua resposta para conter essas informações :) #
Shrikant Sharat
3
Concordo plenamente em não adicionar .a $PATH. Idéia muito perigosa.
Nathan Osman
1

Além de outras respostas, aqui a parte essencial da man bashqual explica isso bem:

EXECUÇÃO DE COMANDO
       Após um comando ser dividido em palavras, se resultar em um simples
       comando e uma lista opcional de argumentos, as seguintes ações são
       ocupado.

       Se o nome do comando não contiver barras, o shell tentará localizar
       isto. Se existir uma função shell com esse nome, essa função será
       invocado como descrito acima em FUNCTIONS. Se o nome não corresponder a
       , o shell o procura na lista de componentes internos do shell. E se
       for encontrada uma correspondência, esse builtin é chamado.

       Se o nome não for uma função shell nem um builtin, e não contiver
       barras, o bash procura em cada elemento do PATH por um diretório con-
       mantendo um arquivo executável com esse nome.
mook765
fonte
0

Um './' faz sentido quando você executa um programa conhecido por você e específico, por exemplo, o seu próprio. Este programa deve estar presente no seu diretório atual. Um './' não faz sentido quando você executa um comando padrão que está em algum lugar do $ PATH. Um comando "qual comando executar" informa onde o comando executar está no $ PATH.

user7346
fonte
0
$ gcc hello.c -o /path/to/someplace/hello

produzirá um executável em algum local. Se esse local estiver no seu caminho, você poderá executar o arquivo. Você pode criar um script se quiser criar um rótulo para a ação "compile esse código-fonte usando o gcc e coloque um executável em algum local que esteja no seu caminho"

Eu sugiro que você crie um novo diretório chamado "testbin" ou algo desse tipo e o coloque no seu caminho para manter os diretórios de caminho existentes limpos.

Jon Kiparsky
fonte
0

./elimina a pesquisa desnecessária de um caminho. ./força a procurar apenas no diretório atual. Se não dermos ./, ele procurará vários caminhos definidos no sistema /usr/bin, como /usr/sbin/, etc.

user175959
fonte
0

"./" significa que você deseja executar um arquivo no diretório atual; é um atalho para digitar todo o caminho, por exemplo:

[root@server ~]#/path/to/file/file.pl

é o mesmo que:

[root@server file]#./file.pl

no exemplo anterior, você passou pelo diretório e seus subdiretórios para o local do arquivo e usou "./" para executar o arquivo no diretório atual.

aquele antes dele " [root @ server ~] # / caminho / para / arquivo / arquivo.pl " também executará o arquivo se você tiver preguiça de "cd" no caminho para o local do arquivo.

Khaled Moustafa
fonte
-4

É muito simples e tem muitos usos.

  1. Quando várias versões do mesmo aplicativo são instaladas, elas estarão disponíveis em um caminho diferente, mas um link virtual para o seu binário pode ser criado /usr/bin. Por exemplo, o Python 2.7, o Python 2.6 está instalado, mas / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Se você estiver no caminho /usr/local/bine executar o Python, ele sempre executará o Python 2.7. A especificação .assumirá o executável da pasta atual.

  1. .- sempre representa executar a partir do diretório atual. E ..sempre significa executa do diretório anterior.
Ramjee Anna
fonte