Pourquoi est-ce que find imprime un «./» de tête si aucun chemin n'est indiqué?


13

Pourquoi est-ce qui findimprime un conduit ./à des résultats si aucun chemin n'est indiqué?

$ find
./file1
./file2
./file3

Quelle est la raison de ne pas l'imprimer?

$ find
file1
file2
file3

Réponses:


16

La raison pour laquelle vous voyez cela est que le développeur de GNU a choisi de fournir un comportement "raisonnable" quand aucun chemin n'est indiqué. En revanche, POSIX n'indique pas que le paramètre est facultatif:find find

L' findutilitaire doit récursivement descendre la hiérarchie de répertoires de chaque fichier spécifié par chemin , en évaluant une expression booléenne composée des primaires décrites dans la section OPERANDS pour chaque fichier rencontré. Chaque opérande de chemin doit être évalué tel qu'il a été fourni, y compris tous les <slash>caractères de fin ; tous les chemins d'accès pour les autres fichiers rencontrés dans la hiérarchie doivent consister en la concaténation de l'opérande de chemin d'accès actuel, a <slash>si l'opérande de chemin d'accès actuel ne s'est pas terminé par un, et le nom de fichier relatif à l'opérande de chemin d'accès. La partie relative ne doit contenir aucun composant point ou point-point, pas de finet uniquement des <slash>caractères uniques entre les composants de chemin d'accès.

Vous pouvez voir la différence dans le synopsis pour chacun. GNU a (comme c'est la convention) des éléments optionnels entre crochets:

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

alors que POSIX n'indique pas qu'il peut être facultatif:

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

Dans le programme GNU, cela se fait en ftsfind.c:

  si (vide)
    {
      / *
       * Nous utilisons ici une variable temporaire car certaines actions modifient
       * le chemin temporairement. Par conséquent, si nous utilisons une constante de chaîne,
       * nous obtenons un coredump. Le meilleur exemple de cela est si nous disons
       * "find -printf% H" (notez, pas "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      return find (defaultpath);
    }

et un littéral "."est utilisé pour plus de simplicité. Vous verrez donc le même résultat avec

find

et

find .

car (et POSIX est d'accord) le chemin donné sera utilisé pour préfixer les résultats (voir ci-dessus pour la concaténation ).

Avec un peu de travail, on pouvait déterminer quand la fonctionnalité a été ajoutée pour la première fois; il était présent lors de la création initiale de "findutils" en 1996 (voir 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);
+}

Dans le journal des modifications de la découverte 3.8, cela était apparemment

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

Habituellement, on fait un post-traitement des fichiers et, dans ce cas, il peut y avoir un énorme avantage à démarrer le nom de fichier avec ./. En particulier, si un nom de fichier commence par -, une commande ultérieure pourrait interpréter ce nom de fichier comme une option. ./évite cela.

Par exemple, considérons un répertoire avec ces fichiers:

$ ls
--link  --no-clobber

Maintenant, imaginez comment cette commande fonctionnerait si les noms de fichiers étaient fournis sans le ./devant:

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

Nous pouvons illustrer le problème avec findlui-même. Exécutons-le dans le même répertoire que ci-dessus. Les oeuvres suivantes:

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

Échoue:

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

1
Ca a du sens. Mais ensuite, il y a la question de savoir pourquoi il ne précède pas un "." quand tu cours find *.
— nr

@nr Bon point. Je m'attends à ce qu'il se comporte de cette façon pour une sorte de compatibilité historique. J'ai ajouté à la réponse un exemple de la raison pour laquelle il s'agit d'un comportement indésirable.
— John1024

3
Certaines versions de file demandent à l'utilisateur de donner un chemin (comme la découverte BSD sur OS X). Donc, vous devez généralement dire explicitement quelque chose comme find . -type f .... À partir de là, ce n'est pas un grand pas pour certaines versions de find (comme GNU find) de simplement par défaut .et de laisser tout le reste tel quel.
— ilkkachu

1
La raison de find *ne pas afficher le .est parce que *répertorie tous les fichiers et dossiers, mais exclut .. Faites-le echo *dans un répertoire qui ne contient qu'un ou deux fichiers, et vous verrez qu'il .n'est pas répertorié. Ainsi, find *opère sur chaque fichier développé. C'est la même chose que si vous aviez dit find Desktop/depuis le répertoire personnel. Vous verrez la sortie commeDesktop/foo_bar.txt
— Sergiy Kolodyazhnyy

1
@ John1024: Je pense que Mrigesh et Thomas Dickey ont correctement répondu à la question. Cette réponse indique pourquoi il est commode de findse comporter ainsi. Avez-vous des informations de référence faisant autorité pour étayer l'allégation implicite qui a findété conçue pour se comporter de cette manière pour cette raison?
— G-Man dit `` Réintègre Monica ''

4

La findcommande a besoin de chemin (s) pour rechercher. Si nous n'en spécifions aucun, il utilise le répertoire courant ( .) comme point de départ. De même, si vous passez le chemin, par exemple /tmp, il considère cela comme son point de départ. Et donc les résultats.

Si répertoire courant:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Si /tmprépertoire:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Si abcrépertoire sous le répertoire courant:

        $ find abc

output:
        abc/file6
        abc/file7

Si plusieurs répertoires sous le répertoire actuel:

        $ find fu bar

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

Oui, je suis d'accord a findbesoin d'un chemin pour rechercher quoi que ce soit et qu'il par défaut dans le répertoire actuel. La question est de savoir pourquoi il imprime le ./début quand file.txtest le même que ./file.txt.
— nr

1
ce n'est pas que trouver ajoute "." au début, il ajoute tout ce que vous lui donnez comme chemin, que ce soit "/ tmp" "abc" ou ".". Il renverra respectivement toutes les valeurs.
— Mrigesh Priyadarshi

-2

Si vous ne spécifiez pas de chemin, la findcommande suppose ${PWD}que comme chemin et l'imprime sur sa sortie. L'utilisateur qui ne spécifie pas le chemin ne change pas le findfonctionnement. Et find fonctionne toujours avec les chemins par défaut.


1
Je vois. Mais si vous l'exécutez sous /tmp, ce $PWDn'est /tmppas le cas ./.
— nr

si vous voulez voir le précédent /tmp, exécutez la commande find /tmpSi vous ne spécifiez pas de chemin, ce sera toujours le répertoire courant, qui est./
— MelBurslan

1
Ce n'est pas que je veuille voir précéder /tmp. C'est que ça ne peut pas être $PWD.
— nr

Mes excuses ${PWD}étaient le verbiage incorrect
— MelBurslan

2
Non, il n'assume pas $ PWD. Comparez la sortie de find ., find $PWDet find(sans chemin, si votre recherche le prend en charge).
— ilkkachu
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.