Por que find imprime um './' inicial se nenhum caminho é fornecido?

13

Por que é que findimprime uma liderança ./para resultados se nenhum caminho é dado?

$ find
./file1
./file2
./file3

Qual é o motivo para não imprimir isso?

$ find
file1
file2
file3
nr
fonte

Respostas:

16

A razão pela qual você vê isso é porque o desenvolvedor do GNU escolheu fornecer um comportamento "razoável" para quando nenhum caminho for fornecido. Por outro lado, o POSIX não afirma que o parâmetro é opcional:find find

O findutilitário deve descer recursivamente a hierarquia de diretórios de cada arquivo especificado pelo caminho , avaliando uma expressão booleana composta pelas primárias descritas na seção OPERANDS para cada arquivo encontrado. Cada operando de caminho deve ser avaliado inalterado conforme foi fornecido, incluindo todos os <slash>caracteres finais ; todos os nomes de caminho para outros arquivos encontrados na hierarquia consistirão na concatenação do operando do caminho atual, a <slash>se o operando do caminho atual não terminar em um e o nome do arquivo relativo ao operando do caminho. A parte relativa não deve conter componentes de ponto ou ponto, ponto à direitacaracteres e apenas <slash>caracteres únicos entre os componentes do nome do caminho.

Você pode ver a diferença na sinopse para cada um. O GNU tem (como é a convenção) itens opcionais entre colchetes:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...]
       [expression]

enquanto POSIX não indica que pode ser opcional:

find [-H|-L] path... [operand_expression...]

No programa GNU, isso é feito em ftsfind.c:

  se (vazio)
    {
      / *
       * Usamos uma variável temporária aqui porque algumas ações modificam
       * o caminho temporariamente. Portanto, se usarmos uma constante de string,
       * temos um coredump. O melhor exemplo disso é se dissermos
       * "find -printf% H" (observe, não "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      return find (caminho padrão);
    }

e um literal "."é usado para simplificar. Então você verá o mesmo resultado com

find

e

find .

porque (e POSIX concorda) o caminho fornecido será usado para prefixar os resultados (veja acima para concatenação ).

Com um pouco de trabalho, era possível determinar quando o recurso foi adicionado pela primeira vez; esteve presente na criação inicial de "findutils" em 1996 (ver find.c):

+  /* If no paths are given, default to ".".  */
+  for (i = 1; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
+    process_top_path (argv[i]);
+  if (i == 1)
+    process_top_path (".");
+
+  exit (exit_status);
+}

No registro de alterações da descoberta 3.8, isso foi aparentemente

Sat Dec 15 19:01:12 1990  David J. MacKenzie  (djm at egypt)

        * find.c (main), util.c (usage): Make directory args optional,
        defaulting to "."
Thomas Dickey
fonte
11

Geralmente, é feito o pós-processamento dos arquivos e, nesse caso, pode haver uma enorme vantagem em iniciar o nome do arquivo ./. Em particular, se um nome de arquivo começar -, um comando subseqüente poderá interpretar esse nome de arquivo como uma opção. ./evita isso.

Como exemplo, considere um diretório com estes arquivos:

$ ls
--link  --no-clobber

Agora, imagine como esse comando funcionaria se os nomes dos arquivos fossem fornecidos sem o nome ./da frente:

$ find -type f -exec cp -t ../ {} +

Podemos ilustrar o problema consigo findmesmo. Vamos executá-lo no mesmo diretório que acima. Os seguintes trabalhos:

$ find ./*
./--link
./--no-clobber

O seguinte falha:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.
John1024
fonte
1
Faz sentido. Mas há a questão de por que não acrescenta um '.' quando você corre find *.
nr
Bom ponto. Espero que se comporte dessa maneira para algum tipo de compatibilidade histórica. Adicionei à resposta um exemplo de por que esse é um comportamento indesejável.
precisa saber é o seguinte
3
Algumas versões file exigem que o usuário forneça um caminho (como o BSD encontra no OS X). Então, você geralmente precisa dizer algo parecido find . -type f .... A partir daí, não é um grande passo para algumas versões do find (como o GNU find) simplesmente padronizar .e deixar todo o resto como está.
Ilkkachu
1
O motivo para find *não mostrar o .é porque *lista todos os arquivos e pastas, mas exclui .. Faça echo *em um diretório que contenha apenas um ou dois arquivos e você verá que .não está listado. Assim, find *opera em cada arquivo expandido. É o mesmo que se você dissesse find Desktop/no diretório inicial. Você verá a saída comoDesktop/foo_bar.txt
Sergiy Kolodyazhnyy 6/08/16
1
@ John1024: Acredito que Mrigesh e Thomas Dickey tenham respondido corretamente à pergunta. Esta resposta indica por que é conveniente que findse comporte dessa maneira. Você tem alguma informação de referência autorizada para apoiar a reivindicação implícita que findfoi projetada para se comportar dessa maneira por esse motivo?
G-Man diz 'Restabelecer Monica
4

O findcomando precisa de caminhos para pesquisar. Se não especificarmos nenhum, ele usará o diretório atual ( .) como ponto de partida. Da mesma forma, se você passar o caminho, por exemplo /tmp, ele considera isso como seu ponto de partida. E, portanto, os resultados.

Se o diretório atual:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

/tmpDiretório If :

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

abcDiretório If no diretório atual:

        $ find abc

output:
        abc/file6
        abc/file7

Se vários diretórios no diretório atual:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9
Mrigesh Priyadarshi
fonte
Sim, concordo que findprecisa de um caminho para pesquisar qualquer coisa e que o padrão seja o diretório atual. A questão é por que ele imprime o líder ./quando file.txté exatamente o mesmo que ./file.txt.
nr
1
não é que encontrar acrescenta "." no início, na verdade, ele adiciona o que você especificar como caminho, seja "/ tmp" "abc" ou ".". Ele retornará todos os valores, respectivamente.
Mrigesh Priyadarshi 5/08
-2

Se você não especificar um caminho, o findcomando assumirá ${PWD}o caminho e o imprimirá em sua saída. O usuário que não especifica o caminho não muda a maneira como findfunciona. E encontrar sempre funciona com caminhos por padrão.

MelBurslan
fonte
1
Entendo. Mas se você executá-lo sob /tmp, então não $PWDé . /tmp./
nr
se você quiser ver precedente /tmp, execute o comando find /tmpSe você não especificar um caminho que será sempre diretório atual, que é./
MelBurslan
1
Não é que eu queira ver preceder /tmp. É que não pode ser $PWD.
nr
Minhas desculpas ${PWD}foi o palavreado incorreta
MelBurslan
2
Não, ele não assume $ PWD. Compare a saída de find ., find $PWDe find(sem um caminho, se a sua descoberta o suportar).
Ilkkachu