¿Es posible usar 2 comandos en la -exec
parte de find
comando?
He intentado algo como:
find . -name "*" -exec chgrp -v new_group {} ; chmod -v 770 {} \;
y obtengo:
buscar: falta un argumento para -exec
chmod: no se puede acceder {}: no existe ese archivo o directorio
chmod: no se puede acceder;: no existe tal archivo o directorio
Comentarios
Responder
En cuanto al comando find
, también puede agregar más comandos -exec
seguidos:
find . -name "*" -exec chgrp -v new_group "{}" \; -exec chmod -v 770 "{}" \;
Tenga en cuenta que este comando es, en su resultado t, equivalente a usar
chgrp -v archivo nuevo_grupo & & archivo chmod -v 770
en cada archivo.
Todos los parámetros de find
«como -name
, -exec
, -size
y así sucesivamente, son en realidad pruebas : find
continuará ejecutándolos uno por uno siempre que la cadena completa hasta ahora se haya evaluado como verdadero . Por lo tanto, cada comando -exec
consecutivo se ejecuta solo si los anteriores devolvieron verdadero (es decir, 0
estado de salida de los comandos). Pero find
también comprende operadores lógicos como o (-o
) y no (!
). Por lo tanto, para usar una cadena de -exec
pruebas independientemente de los resultados anteriores, uno necesitaría usar algo como esto:
find . -name "*" \( -exec chgrp -v new_group {} \; -o -true \) -exec chmod -v 770 {} \;
Comentarios
- +1: Sí, eso ' es la forma más elegante de hacerlo. Si puede explicarnos por qué utiliza
'{}'
(apóstrofos alrededor de las llaves), visite: unix.stackexchange.com/q/ 8647/4485 - @user Desafortunadamente, no ' sé si todavía es necesario. Hice algunas pruebas hace un momento y no ' me encontré con una situación en la que cambiaría algo. Supongo que ' solo " buenas prácticas " se extinguirá.
- Las comillas son importantes para archivos con espacios en sus nombres.
- @ naught101 No, las comillas pueden ser necesarias en algunos shells no estándar, como
fish
ycsh
, pero definitivamente no son necesarios en shells similares a POSIX (sh
,dash
,bash
,zsh
,ksh
,yash
).
Responder
find . -name "*" -exec sh -c "chgrp -v new_group "$0" ; chmod -v 770 "$0"" {} \;
Comentarios
- @Gilles: Las maravillas de
-c
' s extraño manejo de $ 0 me hace pensar que esto está mal cada vez que lo miro, pero definitivamente es correcto. - Me gusta que se defina el shell explícito …
- Esta respuesta (y Giles ' es un swer) parece ser la mejor respuesta para la pregunta dada la
sh -c
.
Respuesta
Su comando es analizado primero por el shell en dos comandos separados por un ;
, 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 -c
si 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 al caparazón; es el argumento cero (que normalmente es el nombre del shell o script, pero esto no importa aquí), por lo que se hace referencia a él como "$0"
.
Puede pasar varios nombres de archivo al shell a la vez y hacer que el shell repita a través de ellos, será más rápido. Aquí paso _
como 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 buscar nada aquí. En bash, ejecute shopt -s globstar
(póngalo en su ~/.bashrc
) para activar **/
que representa un directorio global recursivo. (En zsh, esto es activo todo el tiempo.) Entonces
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 comando find
es que el shell ignora los archivos dot (archivos cuyo nombre comienza con .
). Para incluirlos, en bash, primero configure GLOBIGNORE=.:..
; en zsh, use **/*(D)
como patrón global.
Comentarios
- Esta respuesta (y la respuesta de Glenn ') parece ser la mejor respuesta para la pregunta dada la
sh -c
. - Tanto
chgrp
comochmod
tienen un-R
opción para operación recursiva.
-name "*"
coincide con todos los nombres, por lo que es ' una prueba no operativa que se puede eliminar. Además, tantochmod
ychgrp
tiene una-R
opción para operaciones recursivas.