標準的な推奨ソリューションは簡単です:
find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+
これにより、システムの最大コマンド ライン長まで、できるだけ多くのファイル名が引数として 1 つのコマンドに追加されます。行がこの長さを超えると、コマンドが複数回呼び出されます。
ファイルごとに 1 回コマンドを呼び出したい場合は、代わりに次のようにすることができます:
find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;
chmod -R a=,u+rwX,go+rX $DIR
どう見ても問題なく動作しているようで、最速である可能性が非常に高いです。
(strace
で確認しました 、そして 1 だけになります fchmodat()
ファイル/ディレクトリごとの syscall -- 644 のファイルと 755 のディレクトリの場合)。
トリックは X
です man chmod
に文書化された許可 、 x
のように動作します ディレクトリのみ -- あなたが望んでいたまさにその区別。
そうでないもの 文書化されているのは、それらが指定されたのと同じ順序で適用されるという私の推測であり、ランダムな順序だけではありませんが、いくつかのバリアントを使用してテストを繰り返した結果、指定された順序で実際に実行されることが確信できました。これは常にこのように機能します。
これは Linux 上にあることに言及する必要がありますが、chmod の BSD マンページをざっと読むと、すべきであることが示唆されます。
sitaram の回答、Peter Cordes のコメント、Fanatique の回答、および harrymc の回答をベンチマークしましたが、この回答が最速の方法です .
平均:
- Deltik の答え* – 7.480 秒
- sitaram の回答 – 12.962 秒 (ベストより 73.275% 遅い)
- Peter Cordes のコメント – 14.414 秒 (ベストより 92.685% 遅い)
- Fanatique の回答 – 14.570 秒 (ベストより 94.772% 遅い)
- harrymc の更新された回答 – 14.791 秒 (ベストより 97.730% 遅い)
- harrymc の元の回答 – 1061.926 秒 (ベストより 14096.113% 遅い)
完全な統計の要約:
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
Deltik のコマンド、ベンチマーク形式:
find "$(pwd)" -type d | xargs -P4 chmod 755 & \ find "$(pwd)" -type f | xargs -P4 chmod 644 & wait
sitaram のコマンド、ベンチマーク形式:
chmod -R a=,u+rwX,go+rX "$(pwd)"
Peter Cordes のコマンド、ベンチマーク形式:
find "$(pwd)" \( -type d -exec chmod 755 {} + \) \ -o \( -type f -exec chmod 644 {} + \)
Fanatique のコマンド、ベンチマーク形式:
find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; \ find "$(pwd)" -type f -print0 | xargs -0 chmod 644
ベンチマーク形式の harrymc の更新されたコマンド:
find "$(pwd)" -type d -exec chmod 755 {} + ; \ find "$(pwd)" -type f -exec chmod 644 {} +
ベンチマーク形式の harrymc のオリジナル コマンド:
find "$(pwd)" -type d -exec chmod 755 {} \; ; \ find "$(pwd)" -type f -exec chmod 644 {} \;
chmod
が 4 並列のおかげで、私のコマンドは最速でした。 ファイルの種類ごとのプロセス。これにより、複数の CPU コアが chmod
を実行できるようになりました これにより、ボトルネックがカーネル I/O スレッドまたはディスクに移動します。
すべてが chmod
内で行われるため、sitaram のコマンドが次点でした。 指図。これにより、次の理由により、他の回答と比較してオーバーヘッドが大幅に削減されます。
- ファイルは 1 回だけスキャンする必要があります (
find
を 1 回実行するのと同様) 2 つではなく)、 - 子プロセスを作成する必要はありません。
ただし、このコマンドは、通常のファイルとディレクトリの間で実行可能ビットの異なる意味を含むトリックに依存しているため、柔軟性が最も低くなります。
find
を 1 つ使用する Peter Cordes のコメント コマンドにより、ディレクトリ エントリの二重検索が防止されます。ファイルが多ければ多いほど、この改善はより実質的になります。子 chmod
を作成するオーバーヘッドがまだあります chmod
よりもかなり遅いのはそのためです。 -唯一の解決策。
Fanatique のコマンドと harrymc の更新されたコマンドの間、find
xargs
にパイプ (find | xargs
) は、結果のストリームが非同期で処理されるため、高速でした。 find
の代わりに -exec
の検索動作を一時停止します 、見つかった結果は xargs
に送信されます 同時処理用。
(ヌルバイト区切り文字 (find -print0 | xargs -0
) は実行時間に影響を与えていないようです。)
新しい chmod
のオーバーヘッドが原因で、harrymc の元のコマンドは遅すぎました。 単一のファイルとフォルダーごとにコマンドを実行し、それぞれが順番に実行されます。
テスト セットアップでは、1001 個のディレクトリに 1000002 個の通常のファイルが含まれていました:
[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
すべてのファイルとフォルダーを 777
に設定しました パーミッション、質問の初期条件など。
次に、コマンドのベンチマークを 10 回行い、そのたびにパーミッションを 777
に復元しました。 chmod -R 0777 "$(pwd)"
で テストを実行する前に。
OUTPUT
で 各ベンチマーク コマンドの出力を含むファイルを表して、以下を使用して平均時間を計算しました:
bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"
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
平均時間:7.480 秒
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
平均時間:12.962 秒
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
平均時間:14.414 秒
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
平均時間:14.570 秒
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
平均時間:14.791 秒
harrymc の元の回答のベンチマークの結果
このコマンドが非常に遅いため、ベンチマークを 1 回だけ実行しました。
[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
かかった時間:1061.926 秒