Die empfohlene Standardlösung ist einfach:
find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+
Dadurch werden so viele Dateinamen wie möglich als Argumente an einen einzelnen Befehl angehängt, bis zur maximalen Befehlszeilenlänge des Systems. Wenn die Zeile diese Länge überschreitet, wird der Befehl mehrfach aufgerufen.
Wenn Sie den Befehl einmal pro Datei aufrufen möchten, können Sie stattdessen Folgendes tun:
find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;
chmod -R a=,u+rwX,go+rX $DIR
scheint gut zu funktionieren und ist sehr wahrscheinlich das schnellste, wie auch immer Sie es betrachten.
(Ich habe mit strace
nachgesehen , und es macht nur eine fchmodat()
Syscall pro Datei/Verzeichnis -- für Dateien mit 644 und für Verzeichnisse mit 755).
Der Trick ist die X
Genehmigung, dokumentiert in man chmod
, das sich wie x
verhält nur für Verzeichnisse - genau die Unterscheidung, die Sie wollten.
Was ist nicht dokumentiert ist meine Vermutung, dass sie in der gleichen Reihenfolge angewendet würden, wie sie angegeben sind, und nicht nur in einer zufälligen Reihenfolge, aber wiederholte Tests mit mehreren Varianten haben mich überzeugt, dass sie tatsächlich in der angegebenen Reihenfolge ausgeführt werden, also bin ich mir ziemlich sicher das wird immer so funktionieren.
Ich sollte erwähnen, dass dies unter Linux ist, obwohl ein flüchtiges Lesen der BSD-Manpage für chmod darauf hindeutet, dass es sollte arbeite auch dort.
Ich habe die Antwort von Sitaram, den Kommentar von Peter Cordes, die Antwort von Fanatique und die Antwort von Harrymc verglichen, aber diese Antwort hat den schnellsten Weg .
Durchschnitt:
- Antwort von Deltik* – 7.480 Sekunden
- Sitarams Antwort – 12,962 Sekunden (73,275 % langsamer als der beste)
- Kommentar von Peter Cordes – 14,414 Sekunden (92,685 % langsamer als der beste)
- Antwort von Fanatique – 14,570 Sekunden (94,772 % langsamer als am besten)
- Harrymcs aktualisierte Antwort – 14,791 Sekunden (97,730 % langsamer als am besten)
- Harrymcs ursprüngliche Antwort – 1061,926 Sekunden (14096,113 % langsamer als am besten)
Vollständige statistische Zusammenfassung:
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
Befehl von Deltik im Benchmark-Format:
find "$(pwd)" -type d | xargs -P4 chmod 755 & \ find "$(pwd)" -type f | xargs -P4 chmod 644 & wait
Sitarams Befehl im Benchmark-Format:
chmod -R a=,u+rwX,go+rX "$(pwd)"
Befehl von Peter Cordes im Benchmark-Format:
find "$(pwd)" \( -type d -exec chmod 755 {} + \) \ -o \( -type f -exec chmod 644 {} + \)
Befehl von Fanatique im Benchmark-Format:
find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; \ find "$(pwd)" -type f -print0 | xargs -0 chmod 644
harrymcs aktualisierter Befehl im Benchmark-Format:
find "$(pwd)" -type d -exec chmod 755 {} + ; \ find "$(pwd)" -type f -exec chmod 644 {} +
harrymcs ursprünglicher Befehl im Benchmark-Format:
find "$(pwd)" -type d -exec chmod 755 {} \; ; \ find "$(pwd)" -type f -exec chmod 644 {} \;
Mein Befehl war dank der vier parallelen chmod
am schnellsten Prozesse pro Dateityp. Dadurch konnten mehrere CPU-Kerne chmod
ausführen , wodurch der Engpass in Richtung der Kernel-I/O-Threads oder der Festplatte verschoben wird.
Sitarams Befehl war der Zweitplatzierte, weil alles innerhalb von chmod
erledigt wird Befehl. Dies reduziert den Overhead im Vergleich zu den anderen Antworten erheblich, weil:
- Die Dateien müssen nur einmal gescannt werden (ähnlich wie bei einem
find
statt zwei) und - Es müssen keine untergeordneten Prozesse erstellt werden.
Dieser Befehl ist jedoch am wenigsten flexibel, da er auf einen Trick angewiesen ist, der die unterschiedliche Bedeutung des ausführbaren Bits zwischen regulären Dateien und Verzeichnissen beinhaltet.
Kommentar von Peter Cordes, der einen find
verwendet Befehl, verhindert das doppelte Suchen von Verzeichniseinträgen. Je mehr Dateien vorhanden sind, desto größer ist diese Verbesserung. Es hat immer noch den Aufwand, das Kind chmod
zu erstellen verarbeitet, weshalb es um einiges langsamer ist als das chmod
-nur Lösung.
Zwischen dem Befehl von Fanatique und dem aktualisierten Befehl von harrymc, find
in xargs
geleitet (find | xargs
) war schneller, da der Ergebnisstrom asynchron verarbeitet wird. Statt find
Anhalten des Suchverhaltens für -exec
, werden die gefundenen Ergebnisse an xargs
gesendet für die gleichzeitige Bearbeitung.
(Das Null-Byte-Trennzeichen (find -print0 | xargs -0
) schien die Laufzeit nicht zu beeinflussen.)
Der ursprüngliche Befehl von harrymc war wegen des Overheads eines neuen chmod
zu langsam Befehl für jede einzelne Datei und jeden einzelnen Ordner, die jeweils nacheinander ausgeführt werden.
Im Testaufbau waren 1000002 reguläre Dateien in 1001 Verzeichnissen enthalten:
[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
Ich setze alle Dateien und Ordner auf 777
Berechtigungen, wie die Anfangsbedingungen der Frage.
Dann habe ich die Befehle zehnmal einem Benchmarking unterzogen und jedes Mal die Berechtigungen auf 777
wiederhergestellt mit chmod -R 0777 "$(pwd)"
bevor Sie den Test ausführen.
Mit OUTPUT
Als Darstellung einer Datei, die die Ausgabe jedes Benchmark-Befehls enthält, habe ich die durchschnittliche Zeit berechnet mit:
bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"
Ergebnisse des Benchmarks von Deltiks Antwort
[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
Durchschnittliche Zeit:7.480 Sekunden
Ergebnisse des Benchmarks der Antwort von 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
Durchschnittliche Zeit:12,962 Sekunden
Ergebnisse des Benchmarks des Kommentars von 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
Durchschnittliche Zeit:14,414 Sekunden
Ergebnisse des Benchmarks der Antwort von 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
Durchschnittliche Zeit:14.570 Sekunden
Ergebnisse des Benchmarks von harrymcs aktualisierter Antwort
[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
Durchschnittliche Zeit:14,791 Sekunden
Ergebnisse des Benchmarks der ursprünglichen Antwort von harrymc
Aufgrund der Langsamkeit dieses Befehls habe ich den Benchmark nur einmal ausgeführt.
[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
Benötigte Zeit:1061,926 Sekunden