¿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

  • Tenga en cuenta que -name "*" coincide con todos los nombres, por lo que es ' una prueba no operativa que se puede eliminar. Además, tanto chmod y chgrp tiene una -R opción para operaciones recursivas.

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 y csh, 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 como chmod tienen un -R opción para operación recursiva.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *