¿Cómo puedo usar dos comandos bash en -exec del comando find?


32

¿Es posible usar 2 comandos en la -execparte del findcomando?

He intentado algo como:

find . -name "*" -exec  chgrp -v new_group {}  ; chmod -v 770 {}  \;

y obtengo:

find: falta argumento para -exec
chmod: no se puede acceder {}: No existe tal archivo o directorio
chmod: no se puede acceder ;: No existe dicho archivo o directorio

Respuestas:


44

En cuanto al findcomando, también puede agregar más -execcomandos seguidos:

find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;

Tenga en cuenta que este comando es, en su resultado, equivalente a usar

archivo chgrp -v nuevo_grupo && archivo chmod -v 770

en cada archivo

Todos los findparámetros 's tales como -name, -exec, -sizeetc., son en realidad pone a prueba : findse continuará ejecutando uno por uno, siempre y cuando toda la cadena hasta el momento ha evaluado a verdadera . Por lo tanto, cada -execcomando consecutivo se ejecuta solo si los anteriores devuelven verdadero (es decir, el 0estado de salida de los comandos). Pero findtambién comprende operadores lógicos como or ( -o) y not ( !). Por lo tanto, para usar una cadena de -execpruebas independientemente de los resultados anteriores, uno debería usar algo como esto:

find . -name "*" \( -exec chgrp -v new_group {} \; -o -exec chmod -v 770 {} \; \)

44
+1: Sí, esa es la forma más elegante de hacerlo. Si puede explicar por qué usa '{}'(apóstrofos alrededor de las llaves), visite: unix.stackexchange.com/q/8647/4485
— usuario desconocido el

1
@user Desafortunadamente, no sé si aún es necesario. Hice algunas pruebas en este momento y no me he encontrado con una situación en la que cambiaría nada. Supongo que es solo una "buena práctica" lo que desaparecerá.
— rozcietrzewiacz

2
Las comillas son importantes para archivos con espacios en sus nombres.
— naught101

17
find . -name "*" -exec sh -c 'chgrp -v new_group "$0" ; chmod -v 770 "$0"' {} \;

@Gilles: Las maravillas del -cmanejo extraño de $ 0 me hacen pensar que esto está mal cada vez que lo miro, pero definitivamente es correcto.
— derobert

Me gusta que se defina el shell explícito ...
— djangofan

Esta respuesta (y la respuesta de Giles) parece ser la mejor respuesta para la pregunta dada la sh -c.

14

El comando analiza primero su comando en dos comandos separados por a ;, que es equivalente a una nueva línea:

find . -name "*" -exec chgrp -v new_group {}
chmod -v 770 {} \;

Si desea ejecutar un comando de shell, invoque un shell explícitamente con bash -c(o sh -csi no le importa que el shell sea específicamente bash):

find . -name "*" -exec sh -c 'chgrp -v new_group "$0"; chmod -v 770 "$0"' {} \;

Tenga en cuenta el uso de {}como argumento para el shell; es el argumento cero (que normalmente es el nombre del shell o script, pero esto no importa aquí), por lo tanto, se hace referencia a él como "$0".

Puede pasar varios nombres de archivo al shell a la vez y hacer que el shell los repita, será más rápido. Aquí paso _como el nombre del script y los siguientes argumentos son nombres de archivo, que for x(un atajo para for x in "$@") itera.

find . -name "*" -exec sh -c 'for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done' _ {} +

Tenga en cuenta que desde bash 4, o en zsh, no necesita encontrar nada aquí. En bash, ejecuta shopt -s globstar(ponlo en tu ~/.bashrc) para activar la **/posición de un globo de directorio recursivo. (En zsh, esto está activo todo el tiempo). Luego

chgrp -v new_group -- **/*; chmod -v 770 -- **/*

o si desea que los archivos se repitan en orden

for x in **/*; do
  chgrp -v new_group -- "$x"
  chmod -v 770 -- "$x"
done

Una diferencia con el findcomando es que el shell ignora los archivos de puntos (archivos cuyo nombre comienza con a .). Para incluirlos, en bash, primer set GLOBIGNORE=.:..; en zsh, úsalo **/*(D)como patrón glob.


Esta respuesta (y la respuesta de Glenn) parece ser la mejor respuesta para la pregunta dada la sh -c.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.