La solución estándar recomendada es sencilla:
find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+
Esto agregará tantos nombres de archivo como sea posible como argumentos a un solo comando, hasta la longitud máxima de la línea de comando del sistema. Si la línea excede esta longitud, el comando se llamará varias veces.
Si desea llamar al comando una vez por archivo, puede hacer lo siguiente:
find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;
chmod -R a=,u+rwX,go+rX $DIR
parece funcionar bien, y es muy probable que sea el más rápido, se mire por donde se mire.
(Comprobé con strace
, y solo hace uno fchmodat()
syscall por archivo/directorio:para archivos con 644 y para directorios con 755).
El truco es el X
permiso, documentado en man chmod
, que actúa como x
solo para directorios, la misma distinción que deseaba.
Lo que no es documentado es mi suposición de que se aplicarían en la misma secuencia en que se especifican, y no solo en un orden aleatorio, pero las pruebas repetidas con varias variantes me han convencido de que sí se ejecutan en el orden dado, así que estoy bastante seguro esto siempre va a funcionar así.
Debo mencionar que esto está en Linux, aunque una lectura superficial de la página de manual de BSD para chmod sugiere que debería trabajar allí también.
Comparé la respuesta de sitaram, el comentario de Peter Cordes, la respuesta de Fanatique y la respuesta de harrymc, pero esta respuesta tiene la forma más rápida .
Promedios:
- Respuesta de Deltik*:7,480 segundos
- respuesta de sitaram:12,962 segundos (73,275 % más lento que el mejor)
- Comentario de Peter Cordes:14,414 segundos (92,685 % más lento que el mejor)
- Respuesta de Fanatique:14,570 segundos (94,772 % más lento que el mejor)
- respuesta actualizada de harrymc:14,791 segundos (97,730 % más lento que el mejor)
- respuesta original de harrymc:1061,926 segundos (14096,113 % más lento que el mejor)
Resumen estadístico completo:
Author N min q1 median q3 max mean stddev
------------------ -- ------- ------- ------- ------- ------- ------- --------
Deltik 10 7.121 7.3585 7.4615 7.558 8.005 7.4804 0.248965
sitaram 10 12.651 12.803 12.943 13.0685 13.586 12.9617 0.276589
Peter Cordes 10 14.096 14.2875 14.375 14.4495 15.101 14.4136 0.269732
Fanatique 10 14.219 14.512 14.5615 14.6525 14.892 14.5697 0.211788
harrymc (updated) 10 14.38 14.677 14.8595 14.9025 15.119 14.791 0.21817
harrymc (original) 1 1061.93 1061.93 1061.93 1061.93 1061.93 1061.93 N/A
Comando de Deltik, en formato de referencia:
find "$(pwd)" -type d | xargs -P4 chmod 755 & \ find "$(pwd)" -type f | xargs -P4 chmod 644 & wait
comando de sitaram, en formato de referencia:
chmod -R a=,u+rwX,go+rX "$(pwd)"
Comando de Peter Cordes, en formato de referencia:
find "$(pwd)" \( -type d -exec chmod 755 {} + \) \ -o \( -type f -exec chmod 644 {} + \)
Comando de Fanatique, en formato de referencia:
find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; \ find "$(pwd)" -type f -print0 | xargs -0 chmod 644
comando actualizado de harrymc, en formato de referencia:
find "$(pwd)" -type d -exec chmod 755 {} + ; \ find "$(pwd)" -type f -exec chmod 644 {} +
comando original de harrymc, en formato de referencia:
find "$(pwd)" -type d -exec chmod 755 {} \; ; \ find "$(pwd)" -type f -exec chmod 644 {} \;
Mi comando fue el más rápido gracias a los cuatro paralelos chmod
procesos por tipo de archivo. Esto permitió que múltiples núcleos de CPU ejecutaran chmod
, que mueve el cuello de botella hacia los subprocesos de E/S del kernel o el disco.
el comando de sitaram quedó en segundo lugar porque todo se hace dentro del chmod
dominio. Esto reduce sustancialmente los gastos generales en comparación con las otras respuestas porque:
- Los archivos solo necesitan escanearse una vez (similar a hacer uno
find
en lugar de dos), y - No es necesario crear procesos secundarios.
Este comando es el menos flexible, sin embargo, porque se basa en un truco que involucra el significado diferente del bit ejecutable entre archivos y directorios normales.
El comentario de Peter Cordes, que usa un find
comando, evita búsquedas dobles de entradas de directorio. Cuantos más archivos haya, más sustancial será esta mejora. Todavía tiene la sobrecarga de crear un hijo chmod
procesos, por lo que es un poco más lento que el chmod
-única solución.
Entre el comando de Fanatique y el comando actualizado de harrymc, find
conectado a xargs
(find | xargs
) fue más rápido porque el flujo de resultados se procesa de forma asíncrona. En lugar de find
pausando su comportamiento de búsqueda para -exec
, los resultados encontrados se envían a xargs
para procesamiento concurrente.
(El delimitador de bytes nulos (find -print0 | xargs -0
) no pareció afectar el tiempo de ejecución).
El comando original de harrymc era demasiado lento debido a la sobrecarga de un nuevo chmod
comando para cada archivo y carpeta, cada uno ejecutado en secuencia.
En la configuración de prueba, había 1000002 archivos normales contenidos en 1001 directorios:
[email protected]:~# echo {0..999} | xargs mkdir -p [email protected]:~# find -type d -exec bash -c "cd {}; echo {0..999} | xargs touch" \; [email protected]:~# find | wc -l 1001003 [email protected]:~# find -type d | wc -l 1001 [email protected]:~# find -type f | wc -l 1000002
Configuré todos los archivos y carpetas para tener 777
permisos, como las condiciones iniciales de la pregunta.
Luego, comparé los comandos diez veces, cada vez restaurando los permisos a 777
con chmod -R 0777 "$(pwd)"
antes de ejecutar la prueba.
Con OUTPUT
representando un archivo que contiene la salida de cada comando de referencia, calculé el tiempo promedio usando:
bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"
Resultados del benchmark de la respuesta de Deltik
[email protected]:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d | xargs -P4 chmod 755 & find "$(pwd)" -type f | xargs -P4 chmod 644 & wait ; } ; done [1] 9791 [2] 9793 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.634s user 0m2.536s sys 0m23.384s [1] 9906 [2] 9908 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.443s user 0m2.636s sys 0m23.106s [1] 10021 [2] 10023 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m8.005s user 0m2.672s sys 0m24.557s [1] 10136 [2] 10138 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.480s user 0m2.541s sys 0m23.699s [1] 10251 [2] 10253 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.397s user 0m2.558s sys 0m23.583s [1] 10366 [2] 10368 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.482s user 0m2.601s sys 0m23.728s [1] 10481 [2] 10483 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.679s user 0m2.749s sys 0m23.395s [1] 10596 [2] 10598 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.243s user 0m2.583s sys 0m23.400s [1] 10729 [2] 10731 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.320s user 0m2.640s sys 0m23.403s [1] 10844 [2] 10847 [1]- Done find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Done find "$(pwd)" -type f | xargs -P4 chmod 644 real 0m7.121s user 0m2.490s sys 0m22.943s
Tiempo medio:7.480 segundos
Resultados del benchmark de la respuesta de sitaram
[email protected]:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time chmod -R a=,u+rwX,go+rX "$(pwd)" ; done real 0m12.860s user 0m0.940s sys 0m11.725s real 0m13.059s user 0m0.896s sys 0m11.937s real 0m12.819s user 0m0.945s sys 0m11.706s real 0m13.078s user 0m0.855s sys 0m12.000s real 0m12.653s user 0m0.856s sys 0m11.667s real 0m12.787s user 0m0.820s sys 0m11.834s real 0m12.651s user 0m0.916s sys 0m11.578s real 0m13.098s user 0m0.939s sys 0m12.004s real 0m13.586s user 0m1.024s sys 0m12.372s real 0m13.026s user 0m0.976s sys 0m11.910s
Tiempo medio:12,962 segundos
Resultados del benchmark del comentario de Peter Cordes
[email protected]:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time find "$(pwd)" \( -type d -exec chmod 755 {} + \) -o \( -type f -exec chmod 644 {} + \) ; done real 0m14.096s user 0m1.455s sys 0m12.456s real 0m14.492s user 0m1.398s sys 0m12.897s real 0m14.309s user 0m1.518s sys 0m12.576s real 0m14.451s user 0m1.477s sys 0m12.776s real 0m15.101s user 0m1.554s sys 0m13.378s real 0m14.223s user 0m1.470s sys 0m12.560s real 0m14.266s user 0m1.459s sys 0m12.609s real 0m14.357s user 0m1.415s sys 0m12.733s real 0m14.393s user 0m1.404s sys 0m12.830s real 0m14.448s user 0m1.492s sys 0m12.717s
Tiempo medio:14.414 segundos
Resultados del benchmark de la respuesta de Fanatique
[email protected]:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; find "$(pwd)" -type f -print0 | xargs -0 chmod 644 ; } ; done real 0m14.561s user 0m1.991s sys 0m13.343s real 0m14.521s user 0m1.958s sys 0m13.352s real 0m14.696s user 0m1.967s sys 0m13.463s real 0m14.562s user 0m1.875s sys 0m13.400s real 0m14.609s user 0m1.841s sys 0m13.533s real 0m14.892s user 0m2.050s sys 0m13.630s real 0m14.291s user 0m1.885s sys 0m13.182s real 0m14.843s user 0m2.066s sys 0m13.578s real 0m14.219s user 0m1.837s sys 0m13.145s real 0m14.503s user 0m1.803s sys 0m13.419s
Tiempo medio:14.570 segundos
Resultados del benchmark de la respuesta actualizada de harrymc
[email protected]:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -exec chmod 755 {} + ; find "$(pwd)" -type f -exec chmod 644 {} + ; } ; done real 0m14.975s user 0m1.728s sys 0m13.050s real 0m14.710s user 0m1.586s sys 0m12.979s real 0m14.644s user 0m1.641s sys 0m12.872s real 0m14.927s user 0m1.706s sys 0m13.036s real 0m14.867s user 0m1.597s sys 0m13.086s real 0m15.119s user 0m1.666s sys 0m13.259s real 0m14.878s user 0m1.590s sys 0m13.098s real 0m14.852s user 0m1.681s sys 0m13.045s real 0m14.380s user 0m1.603s sys 0m12.663s real 0m14.558s user 0m1.514s sys 0m12.899s
Tiempo medio:14.791 segundos
Resultados del benchmark de la respuesta original de harrymc
Debido a lo lento que era este comando, solo ejecuté el punto de referencia una vez.
[email protected]:~# for i in {0..0} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -exec chmod 755 {} \; ; find "$(pwd)" -type f -exec chmod 644 {} \; ; } ; done real 17m41.926s user 12m26.896s sys 4m58.332s
Tiempo empleado:1061,926 segundos