Existe alguma diferença entre os caminhos "arquivo" e "./arquivo"?

12

Como o título diz, existe alguma diferença para os sistemas de arquivos * NIX? por exemplo ls fileels ./file

Sergey Alaev
fonte
1
Você pode perguntar ao unix.stackexchange.com - as respostas até agora têm boas informações, mas nenhuma delas parece ser a resposta.
Rob Starling

Respostas:

14

Não sou louco pela explicação de SmallLoanOf1M. É tecnicamente correto, mas responde de uma maneira que não corresponde ao exemplo de uso na pergunta.

Então, a título de exemplo, aqui está uma diferença importante entre os dois da questão: "arquivo" e "./arquivo"

E se o arquivo for nomeado com um caractere que é analisado pelo shell? Especialmente em relação aos caracteres interpretados pelo comando que um está executando.

Especificamente, o caractere "traço": "-". Mas outros caracteres são significativos para o shell.

Exemplo. Meu arquivo foi nomeado "-dingle"

Tente listar o arquivo:

ls -dingle
# ls -dingle
ls: invalid option -- 'e'

Pior ainda, e se o arquivo tiver o nome " -rf rmbomb *"? Agora tente removê-lo

rm "-rf rmbomb *"

Nem vou tentar dar esse exemplo, mas espero que você entenda.

Então, como você lista um arquivo com o traço? Use ./na frente.

# ls ./-dingle
./-dingle

O mesmo vale para rm

JDS
fonte
Essa é uma maneira válida de processar alguns arquivos com nomes estranhos, e minha resposta não considerou arquivos assim. Pode-se também usar um literal em todos os exemplos acima, na forma de uma barra invertida que precede caracteres ímpares, incluindo os espaços especificados acima. Um exemplo disso seria: ls \-dingleou ls \-rf\ rmbomb\ \*. Essa pode ser uma boa maneira de garantir que qualquer conjunto de comandos seja pelo menos consistente, pois especificar ./antes que um nome não escape caracteres após o ./.
Spooler
2
Acontece que, como escapes são escapados pelo shell, não pelo comando, e os parâmetros são analisados ​​pelo comando, escapando ou citando o - não faz nada útil.
Dewi Morgan
2
Você faz parecer rm "-rf rmbomb *"que realmente faria algo ruim, em vez de apenas cometer rmum erro de impressão. Só é perigoso se você esquecer de citar o nome do arquivo, para que a divisão de palavras aconteça. (especialmente em um script de shell em que você executa, em rm $filevez de rm "$file". Mas, nesse caso, o *não será expandido, porque a expansão glob não acontece no conteúdo da expansão variável. Se você quiser isso, precisará de um eval.) De qualquer forma, se o seu script dividir os nomes dos arquivos antes de passar para a rm, eu faria um arquivo chamado space -rf .ou algo assim, então rm ./$inão ajuda.
Peter Cordes
1
Aliás, a mensagem de erro real é rm: invalid option -- ' 'quando ele tenta interpretar o espaço depois -rfcomo uma opção de caractere único, porque faz parte do mesmo argumento. (E sim, eu corri isso dentro de uma pasta vazia no caso de eu tinha esquecido alguma coisa e foi realmente perigoso: P)
Peter Cordes
2
@PeterCordes: separar palavras e globbing ocorre nos resultados da expansão de variáveis ​​não citadas e da substituição de comandos, a menos que sejam suprimidas por IFS=''e -frespectivamente. Um exemplo mais raro é que awktrata um operando (que não seja o primeiro operando que é o script) tendo forma foo=barcomo uma atribuição a ser executada, mas ./foo=barcomo um arquivo a ser lido.
Dave_thompson_085 22/10
7

Sim.

Ao emitir filena linha de comando, o BASH pesquisará na variável de ambiente $ PATH um arquivo com esse nome. A menos que o arquivo resida em um diretório dentro da sua variável $ PATH, ele não será encontrado.

.significa o diretório atual. ./significa dentro do diretório atual, em termos relativos. É o equivalente a dizer algo como /home/sheogorath/shivering/isles.imgquando invocar ./isles.imgenquanto estiver trabalhando no /home/sheogorath/shivering/diretório.

Como tal, é comumente usado para executar arquivos dentro do seu diretório de trabalho "no local".

EDIT: No seu exemplo, lsestá sendo chamado pelo shell e encontrado usando a variável path. Seu argumento será processado em seu diretório de trabalho, seja ele qual for. Como esse é o padrão ls, você não verá nenhuma diferença entre especificar filee explicitamente ./file, pois ambos apontam para o diretório atual.

Nem todos os comandos aceitam caminhos de arquivos no diretório ativo, e alguns esperam que você exiba os arquivos em um diretório que eles próprios pré-definem via configuração. Entre os comandos que aceitam arquivos como argumentos, esses comandos são menos comuns

Spooler
fonte
1
Isso é bash, mas eu queria saber sobre a resolução de caminho em geral
Sergey Alaev
1
É assim que qualquer shell que eu já ouvi falar funciona. O BASH é apenas o mais usado.
Spooler
4
$ PATH é relevante apenas para comandos e não tem nada a ver com argumentos de nome de arquivo que seguem um comando como o lsmencionado na pergunta original. Isso é mais a diferença entre refferencing um caminho relativo (relativo ao diretório de trabalho atual) Ie ../../dir/filenamee um caminho absoluto /path/to/dir/filename
HBruijn
1
+1 para Sheogorath ... e uma resposta correta.
Corey Ogburn
1
Se eles são argumentos para um comando que tenta encontrar arquivos no diretório ativo por padrão, eles serão os mesmos. Assim, pois lseles sempre serão o mesmo caminho, um especificado mais explicitamente que o outro. Nem todos os comandos se comportam dessa maneira ao processar argumentos, mas a maioria o faz.
Spooler