¿Qué significa "{} \;" en el comando de búsqueda?

38

A veces veo el siguiente comando:

find . -name  * -exec ls -a {} \;

Me pidieron que ejecutara esto.

¿Qué {} \;significa aquí?

codeofnode
fuente
2
-name *es redundante
Kevin
3
Consulte también explicaciones para otros tipos de preguntas como esta. Aquí está la salida para su comando. .
Glutanimate
10
-name *Es peor que redundante. Debido a *que no está entre comillas, el shell lo expande a la lista de nombres de archivo en la carpeta actual, con espacios que se tratan incorrectamente, lo que genera resultados inesperados o un mensaje de error. Como punto extra, findtiene muchas funciones, una de ellas es listar archivos; Esto evita tener que usar -exec. Por ejemplo, puedes usar find . -printo find . -ls. Por último, hay dos maneras de escapar del punto y coma: o bien como lo hizo con la barra invertida, \;o por citar: ';'. Use el que le resulte más cómodo.
Paddy Landau

Respuestas:

49

Si ejecuta findcon exec, se {}expande al nombre de archivo de cada archivo o directorio encontrado con find(para que lsen su ejemplo obtenga cada nombre de archivo encontrado como argumento; tenga en cuenta que llama lso cualquier otro comando que especifique una vez para cada archivo encontrado).

Semicolon ;finaliza el comando ejecutado por exec. Debe escaparse \para que el shell que ejecuta en su findinterior no lo trate como su propio carácter especial, sino que se lo pase find.

Vea este artículo para más detalles.


Además, findproporciona cierta optimización con exec cmd {} +: cuando se ejecuta así, findagrega los archivos encontrados al final del comando en lugar de invocarlo una vez por archivo (de modo que el comando se ejecuta solo una vez, si es posible).

La diferencia en el comportamiento (si no es en eficiencia) se nota fácilmente si se ejecuta con ls, p. Ej.

find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +

Suponiendo que tiene algunos jpgarchivos (con rutas lo suficientemente cortas ), el resultado es una línea por archivo en el primer caso y el lscomportamiento estándar de mostrar archivos en columnas para el último.

moon.musick
fuente
1
Creo que sería beneficioso para usted para contrastar \;con +.
Kevin
¿En qué se diferencia find . -name * | ls -a -?
András Hummer
@DrH El objetivo no es dejar que Shell realice la expansión de comodines, sino pasar la expresión de comodín a find. Además, la salida de lsen este caso aparentemente no depende de la entrada; no importa lo que use como filtro find, lssolo muestra el contenido del directorio de trabajo y eso es todo. Compruebe por ejemplo find ~ -iname '*.jpg' -exec ls -a {} \;vs find ~ -iname '*.jpg' | ls -a.
moon.musick
@DrH o incluso echo 'foo' | ls -a.
moon.musick
@ moon.musick, creo que te has perdido lo importante -en tu ls -a -comando al probar lo que @ dr-h preguntó.
Daniel Llewellyn
21

Desde la página de manual para el findcomandoIcono de página de manual :

-exec command ;
              Execute  command;  true if 0 status is returned.  All following arguments to find are taken to be arguments to
              the command until an argument consisting of `;' is encountered.  The string `{}' is replaced  by  the  current
              file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
              is alone, as in some versions of find.  Both of these constructions might need to be escaped (with a  `\')  or
              quoted  to  protect them from expansion by the shell.

Así que aquí está la explicación:

{}significa "la salida de find". Como en "lo que sea que se findencuentre". finddevuelve la ruta del archivo que estás buscando, ¿verdad? Entonces lo {}reemplaza; es un marcador de posición para cada archivo que findlocaliza el comando (tomado de aquí ).

La \;parte básicamente dice find"está bien, he terminado con el comando que quería ejecutar".

Ejemplo:

Digamos que estoy en un directorio lleno de .txtarchivos. Entonces corro:

find . -name  '*.txt' -exec cat {} \;

La primera parte, find . -name *.txtdevuelve una lista de los .txtarchivos. La segunda parte, -exec cat {} \;ejecutará el catcomando para cada archivo encontrado por find, por lo que cat file1.txt, cat file2.txty así sucesivamente.

Alaa Ali
fuente
44
La parte *.txtdebe ser citada como '*.txt'. Esto se debe a que si hay .txtarchivos en la carpeta actual, el shell expandirá esto y obtendrá resultados incorrectos o un mensaje de error. find -name '*.txt' -exec cat {} \;
Paddy Landau
@Alaa Ali muy bien explicada
pushya