¿Por qué encuentra print un './' principal si no se dan rutas?

13

¿Por qué es que findimprime un ./resultado importante si no se dan rutas?

$ find
./file1
./file2
./file3

¿Cuál es la razón para no imprimir esto?

$ find
file1
file2
file3
nr
fuente

Respuestas:

16

La razón por la que ve esto es porque el desarrollador de GNU eligió proporcionar un comportamiento "razonable" para cuando no se proporciona ninguna ruta. Por el contrario, POSIX no indica que el parámetro es opcional:find find

La findutilidad descenderá recursivamente la jerarquía de directorios de cada archivo especificado por ruta , evaluando una expresión booleana compuesta de las primarias descritas en la sección OPERANDS para cada archivo encontrado. Cada operando de ruta se evaluará sin modificaciones tal como se proporcionó, incluidos todos los <slash>caracteres finales ; todos los nombres de ruta para otros archivos encontrados en la jerarquía consistirán en la concatenación del operando de ruta actual, a <slash>si el operando de ruta actual no terminó en uno, y el nombre de archivo relativo al operando de ruta. La porción relativa no contendrá componentes de punto o punto-punto, no será posteriorcaracteres y solo <slash>caracteres individuales entre componentes de nombre de ruta.

Puedes ver la diferencia en la sinopsis de cada uno. GNU tiene (como es la convención) elementos opcionales entre corchetes:

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

mientras POSIX no indica que puede ser opcional:

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

En el programa GNU, eso se hace en ftsfind.c:

  si (vacío)
    {
      / *
       * Usamos una variable temporal aquí porque algunas acciones modifican
       * El camino temporalmente. Por lo tanto, si usamos una cadena constante,
       * tenemos un coredump. El mejor ejemplo de esto es si decimos
       * "find -printf% H" (nota, no "find. -printf% H").
       * /
      char defaultpath [2] = ".";
      volver encontrar (defaultpath);
    }

y "."se usa un literal para simplificar. Entonces verás el mismo resultado con

find

y

find .

porque (y POSIX está de acuerdo) la ruta dada se usará para prefijar los resultados (ver arriba para la concatenación ).

Con un poco de trabajo, se podría determinar cuándo se agregó la función por primera vez; estuvo presente en la creación inicial de "findutils" en 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);
+}

Desde el registro de cambios para encontrar 3.8, aparentemente fue

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
fuente
11

Por lo general, uno realiza el procesamiento posterior de los archivos y, en ese caso, puede ser una gran ventaja comenzar con el nombre de archivo ./. En particular, si un nombre de archivo comienza con -, un comando posterior podría interpretar ese nombre de archivo como una opción. ./evita eso.

Como ejemplo, considere un directorio con estos archivos:

$ ls
--link  --no-clobber

Ahora, imagine cómo funcionaría este comando si los nombres de archivo se proporcionaran sin el ./frente:

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

Podemos ilustrar el problema consigo findmismo. Ejecútelo en el mismo directorio que el anterior. Los siguientes trabajos:

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

Lo siguiente falla:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.
John1024
fuente
1
Que tiene sentido. Pero luego está la pregunta de por qué no antepone un '.' cuando se ejecuta find *.
nr
@nr Buen punto. Espero que se comporte así por algún tipo de compatibilidad histórica. Agregué a la respuesta un ejemplo de por qué este comportamiento es indeseable.
John1024
3
Algunas versiones de file exigen que el usuario proporcione una ruta (como el BSD encuentra en OS X). Por lo tanto, generalmente necesita decir explícitamente algo así find . -type f .... A partir de ahí, no es un gran paso para algunas versiones de find (como GNU find) simplemente predeterminar .y dejar todo lo demás como está.
ilkkachu
1
La razón por la que find *no se muestra .es porque *enumera todos los archivos y carpetas, pero excluye .. Haga echo *en un directorio que contenga solo uno o dos archivos, y verá que .no está en la lista. Por lo tanto, find *opera en cada archivo expandido. Es lo mismo que dijiste find Desktop/desde el directorio de inicio. Verá la salida comoDesktop/foo_bar.txt
Sergiy Kolodyazhnyy
1
@ John1024: Creo que Mrigesh y Thomas Dickey han respondido correctamente la pregunta. Esta respuesta indica por qué es conveniente que se findcomporte como lo hace. ¿Tiene alguna información de referencia autorizada para respaldar la afirmación implícita que findfue diseñada para comportarse de esta manera por este motivo?
G-Man dice 'reinstalar a Monica' el
4

El findcomando necesita ruta (s) para buscar. Si no especificamos ninguno, utiliza el directorio actual ( .) como punto de partida. Del mismo modo, si pasa el camino, por ejemplo /tmp, lo considera como su punto de partida. Y por lo tanto los resultados.

Si el directorio actual:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

Si el /tmpdirectorio:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

Si el abcdirectorio está debajo del directorio actual:

        $ find abc

output:
        abc/file6
        abc/file7

Si hay varios directorios en el directorio actual:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9
Mrigesh Priyadarshi
fuente
Sí, acepto que findnecesita una ruta para buscar cualquier cosa y que el valor predeterminado es el directorio actual. La pregunta es por qué imprime el líder ./cuando file.txtes igual que ./file.txt.
nr
1
no es que el hallazgo agrega "." al principio, en realidad agrega lo que le dé como ruta, ya sea "/ tmp" "abc" o ".". Devolverá todos los valores respectivamente.
Mrigesh Priyadarshi
-2

Si no especifica una ruta, el findcomando asume que ${PWD}es la ruta y la imprime en su salida. El usuario que no especifica la ruta no cambia la forma en que findfunciona. Y find siempre funciona con rutas por defecto.

MelBurslan
fuente
1
Veo. Pero si lo ejecutas debajo /tmp, entonces no lo $PWDes . /tmp./
nr
si quieres ver precedentes /tmp, ejecuta el comandofind /tmp Si no especifica una ruta, siempre será el directorio actual, que es./
MelBurslan
1
No es que quiera ver precedentes /tmp. Es que no puede ser $PWD.
nr
Mis disculpas ${PWD}fueron las
palabras
2
No, no asume $ PWD. Compare la salida de find ., find $PWDyfind (sin una ruta, si su búsqueda lo admite).
ilkkachu