Perché find stampa un './' iniziale se non viene fornito alcun percorso?


13

Perché viene findstampato un ./risultato ai risultati se non viene fornito alcun percorso?

$ find
./file1
./file2
./file3

Qual è la ragione per non stampare questo?

$ find
file1
file2
file3

Risposte:


16

Il motivo per cui vedi questo è perché lo sviluppatore di GNU ha scelto di fornire un comportamento "ragionevole" per quando non viene indicato alcun percorso. Al contrario, POSIX non afferma che il parametro è facoltativo:find find

L' findutilità deve ricorsivamente discendere la gerarchia di directory da ciascun file specificato dal percorso , valutando un'espressione booleana composta dalle primarie descritte nella sezione OPERANDS per ciascun file incontrato. Ogni operando di percorso deve essere valutato inalterato come è stato fornito, inclusi tutti i <slash>caratteri finali ; tutti i nomi di percorso per altri file incontrati nella gerarchia devono consistere nella concatenazione dell'operando del percorso corrente, a <slash>se l'operando del percorso corrente non termina in uno e il nome del file relativo all'operando del percorso. La parte relativa non deve contenere componenti punto o punto, nessun trascinamentocaratteri e solo singoli <slash>caratteri tra i componenti del percorso.

Puoi vedere la differenza nella sinossi per ciascuno. GNU ha (come è la convenzione) elementi opzionali tra parentesi quadre:

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

mentre POSIX non indica che può essere facoltativo:

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

Nel programma GNU, questo è fatto in ftsfind.c:

  if (vuoto)
    {
      / *
       * Qui usiamo una variabile temporanea perché alcune azioni modificano
       * il percorso temporaneamente. Quindi se usiamo una costante di stringa,
       * otteniamo un coredump. Il miglior esempio di questo è se diciamo
       * "find -printf% H" (nota, non "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      return find (defaultpath);
    }

e un letterale "."viene usato per semplicità. Quindi vedrai lo stesso risultato con

find

e

find .

perché (e POSIX concorda) verrà utilizzato il percorso indicato per aggiungere il prefisso ai risultati (vedere sopra per la concatenazione ).

Con un po 'di lavoro, si potrebbe determinare quando la funzionalità è stata aggiunta per la prima volta; era presente nella creazione iniziale di "findutils" nel 1996 (vedi 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);
+}

Dal log delle modifiche per trovare 3.8, questo era apparentemente

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 "."

11

Di solito, si esegue la post-elaborazione dei file e, in tal caso, può esserci un enorme vantaggio nell'avvio del nome file ./. In particolare, se un nome file inizia con -, un comando successivo potrebbe interpretare quel nome file un'opzione. ./evita quello.

Ad esempio, considera una directory con questi file:

$ ls
--link  --no-clobber

Ora, immagina come funzionerebbe questo comando se i nomi dei file fossero forniti senza il ./fronte:

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

Possiamo illustrare il problema con findse stesso. Eseguiamolo nella stessa directory di cui sopra. Le seguenti opere:

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

Non riesce:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.

1
Ha senso. Ma poi c'è la domanda sul perché non anteponi un '.' quando corri find *.
n.

@nr Buon punto. Mi aspetto che si comporti in questo modo per una sorta di compatibilità storica. Ho aggiunto alla risposta un esempio del perché si tratta di un comportamento indesiderato.
Giovanni 1024,

3
Alcune versioni file richiedono all'utente di fornire un percorso (come BSD trova su OS X). Quindi di solito devi dire esplicitamente qualcosa del genere find . -type f .... Da lì, non è un grande passo per alcune versioni di find (come GNU find) di default .e lasciare tutto il resto com'è.
ilkkachu,

1
Il motivo per find *non mostrare il .è perché *elenca tutti i file e le cartelle, ma esclude .. Fai echo *in una directory che contiene solo uno o due file e vedrai che .non è elencato. Pertanto, find *opera su ciascun file espanso. È come se dicessi find Desktop/dalla home directory. Vedrai l'output comeDesktop/foo_bar.txt
Sergiy Kolodyazhnyy il

1
@ John1024: credo che Mrigesh e Thomas Dickey abbiano risposto correttamente alla domanda. Questa risposta indica perché è conveniente che findsi comporti in questo modo. Hai qualche autorevole informazione di riferimento a supporto dell'affermazione implicita che è findstata progettata per comportarsi in questo modo per questo motivo?
G-Man dice "Ripristina Monica" il

4

Il findcomando ha bisogno dei percorsi per la ricerca. Se non ne specifichiamo, utilizza la directory corrente ( .) come punto di partenza. Allo stesso modo, se si passa il percorso, ad esempio /tmp, lo considera come punto di partenza. E quindi i risultati.

Se la directory corrente:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Se /tmpdirectory:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Se abcdirectory nella directory corrente:

        $ find abc

output:
        abc/file6
        abc/file7

Se più directory nella directory corrente:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9

Sì, sono d'accordo ha findbisogno di un percorso per cercare qualsiasi cosa e che per impostazione predefinita è la directory corrente. La domanda è: perché stampa il comando ./quando file.txtè uguale a ./file.txt.
n.

1
non è che trovare aggiunge "." all'inizio effettivamente aggiunge qualunque cosa tu gli dia come percorso, sia esso "/ tmp" "abc" o ".". Restituirà rispettivamente tutti i valori.
Mrigesh Priyadarshi,

-2

Se non si specifica un percorso, il findcomando assume ${PWD}come percorso e lo stampa sul suo output. L'utente che non specifica il percorso non cambia il modo in cui findfunziona. E find funziona sempre con i percorsi di default.


1
Vedo. Ma se lo esegui sotto /tmp, allora non lo $PWDè . /tmp./
n.

se vuoi vedere il precedente /tmp, esegui il comando find /tmpSe non specifichi un percorso sarà sempre la directory corrente, che è./
MelBurslan

1
Non è che io voglia vedere ciò che precede /tmp. È che non può essere $PWD.
n.

Le mie scuse sono ${PWD}state la verbosità errata
MelBurslan il

2
No, non presuppone $ PWD. Confronta l'output di find ., find $PWDe find(senza un percorso, se la tua ricerca lo supporta).
ilkkachu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.