個人ディレクトリのバックアップを台無しにしてしまったrsync
(おそらくNTFSファイルシステムでバックアップしているからだろう): すべてのファイルはここにあるが、すべてのファイルとディレクトリのアクセス権が777になっている。魔法再帰的に変更するユーティリティ:
- 777 から 755 までのディレクトリ。
- 777 から 644 までの通常のファイル。私の家には実行可能ファイルがあまりないので、後で手動で管理できます。
- 他のファイル (リンク、その他) は変更しないでください。
シェルで行うのは簡単ですが、何時間もかかります...
補足的な質問: NTFS (またはその他の方法) 上の Linux ディレクトリ階層を適切にバックアップするためのアドバイスはありますかrsync
。
答え1
標準的に推奨される解決策は簡単です。
find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+
これにより、システムの最大コマンド ライン長まで、できるだけ多くのファイル名が単一のコマンドの引数として追加されます。行がこの長さを超えると、コマンドは複数回呼び出されます。
ファイルごとにコマンドを 1 回呼び出す場合は、代わりに次のようにします。
find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;
答え2
chmod -R a=,u+rwX,go+rX $DIR
うまく動作しているようで、どう見てもこれが最速である可能性が高いです。
(私は で確認しましたstrace
が、1つ fchmodat()
ファイル/ディレクトリごとのシステム コール (ファイルの場合は 644、ディレクトリの場合は 755)。
秘訣はX
、 に記載されているman chmod
、x
ディレクトリに対してのみ のように動作する権限です。まさにこれが、あなたが望んでいた区別です。
とはない文書化されているのは、それらが指定されたのと同じ順序で適用され、ランダムな順序で適用されるわけではないという私の推測ですが、いくつかのバリエーションで繰り返しテストした結果、それらは確かに指定された順序で実行されることがわかったので、これが常にこのように機能すると確信しています。
これはLinux上でのことだということを述べておくべきだろうが、BSDのマニュアルページchmodをざっと読むと、すべきそこでも働きます。
答え3
私はベンチマークしたシタラムの答え、ピーター・コーデスのコメント、ファナティックの答え、 そしてharrymc の回答、 しかしこの答えは最速の方法である。
平均:
- Deltikの回答* – 7.480秒
* クレジットピーター・コーデスのために平行性を示唆する - sitaram の回答 – 12.962 秒 (最高より 73.275% 遅い)
- ピーター・コーデスのコメント – 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 のコマンド (ベンチマーク形式):
「$(pwd)」を検索 -type d -print0 | xargs -0 -P4 chmod 755 & \ "$(pwd)" を検索 -type f -print0 | xargs -0 -P4 chmod 644 & wait
sitaram のコマンド (ベンチマーク形式):
chmod -R a=,u+rwX,go+rX "$(pwd)"
ベンチマーク形式の Peter Cordes のコマンド:
「$(pwd)」を検索 \( -type d -exec chmod 755 {} + \) \ -o \( -type f -exec chmod 644 {} + \)
Fanatique のコマンド (ベンチマーク形式):
"$(pwd)" を検索 -type d -print0 | xargs -0 chmod 755 ; \ 「$(pwd)」を検索 -type f -print0 | xargs -0 chmod 644
harrymc の更新されたコマンド (ベンチマーク形式):
「$(pwd)」を検索 -type d -exec chmod 755 {} + ; \ 「$(pwd)」を検索 -type f -exec chmod 644 {} +
harrymc のオリジナルコマンド(ベンチマーク形式):
"$(pwd)" を検索 -type d -exec chmod 755 {} \; ; \ "$(pwd)" -type f -exec chmod 644 {} を検索 \;
私のコマンドは、ファイル タイプごとに 4 つの並列プロセスのおかげで最も高速になりましたchmod
。これにより、複数の CPU コアが実行できるようになりchmod
、ボトルネックがカーネル I/O スレッドまたはディスクに移動しました。
sitaram のコマンドは、すべてがコマンド内で実行されるため、次点となりましたchmod
。これにより、他の回答と比較してオーバーヘッドが大幅に削減されます。その理由は次のとおりです。
- ファイルは一度スキャンするだけで済みます(
find
2回ではなく1回行うのと同様)。 - 子プロセスを作成する必要はありません。
ただし、このコマンドは、通常のファイルとディレクトリ間の実行ビットの意味が異なるというトリックに依存しているため、柔軟性が最も低くなります。
Peter Cordes のコメントは、1 つのfind
コマンドを使用して、ディレクトリ エントリの二重検索を防止します。ファイルが多いほど、この改善はより顕著になります。それでも子chmod
プロセスを作成するオーバーヘッドがあるため、-only ソリューションよりもかなり遅くなりますchmod
。
Fanatique のコマンドと harrymc の更新されたコマンドの間では、結果のストリームが非同期に処理されるため、 find
piped into xargs
( ) の方が高速でした。の検索動作を の間find | xargs
一時停止する代わりに、見つかった結果は に送信され、並行処理されます。 (ヌル バイト区切り文字 ( ) は実行時間に影響を与えないようです。)find
-exec
xargs
find -print0 | xargs -0
chmod
harrymc の元のコマンドは、各ファイルとフォルダーごとに新しいコマンドが順番に実行されるオーバーヘッドが原因で、非常に遅くなりました。
テスト設定では、1001 個のディレクトリ内に 1000002 個の通常ファイルが含まれていました。
root@demo:~# echo {0..999} | xargs mkdir -p root@demo:~# find -type d -exec bash -c "cd {}; echo {0..999} | xargs touch" \; root@demo:~# 検索 | wc -l 1001003 root@demo:~# find -type d | wc -l 1001 root@demo:~# find -type f | wc -l 1000002
777
質問の初期条件のように、すべてのファイルとフォルダーに権限を設定しました。
次に、テストを実行する前777
に権限を復元しながら、コマンドを 10 回ベンチマークしました。chmod -R 0777 "$(pwd)"
OUTPUT
各ベンチマーク コマンドの出力を含むファイルを表し、次のように平均時間を計算しました。
bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"
Deltikの回答のベンチマーク結果
root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 & find "$(pwd)" -type f -print0 | xargs -0 -P4 chmod 644 & wait ; } ; done [1] 9791 [2] 9793 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒634 ユーザー 0分2.536秒 システム 0分23秒384秒 [1] 9906 [2] 9908 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒443 ユーザー 0分2.636秒 システム 0分23秒106秒 [1] 10021 [2] 10023 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分8秒005 ユーザー 0分2.672秒 システム 0分24秒557秒 [1] 10136 [2] 10138 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒480 ユーザー 0分2.541秒 システム 0分23秒699秒 [1] 10251 [2] 10253 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒397 ユーザー 0分2.558秒 システム 0分23秒583秒 [1] 10366 [2] 10368 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒482 ユーザー 0分2.601秒 システム 0分23秒728秒 [1] 10481 [2] 10483 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒679 ユーザー 0分2.749秒 システム 0分23秒395秒 [1] 10596 [2] 10598 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒243 ユーザー 0分2.583秒 システム 0分23秒400秒 [1] 10729 [2] 10731 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒320 ユーザー 0分2.640秒 システム 0分23秒403秒 [1] 10844 [2] 10847 [1]- 完了 find "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ 完了 find "$(pwd)" -type f | xargs -P4 chmod 644 実数 0分7秒121 ユーザー 0分2.490秒 システム 0分22秒943秒
平均時間: 7.480秒
sitaramの回答のベンチマーク結果
root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time chmod -R a=,u+rwX,go+rX "$(pwd)" ; 完了 実数 0分12秒860秒 ユーザー 0m0.940s システム 0分11秒725秒 実数 0分13秒059 ユーザー 0分0.896秒 システム 0分11秒937秒 実数 0分12秒819 ユーザー 0分0.945秒 システム 0分11秒706秒 実数 0分13秒078 ユーザー 0分0.855秒 システム 0分12.000秒 実数 0分12秒653 ユーザー 0分0.856秒 システム 0分11.667秒 実数 0分12秒787 ユーザー 0m0.820s システム 0分11秒834秒 実数 0分12秒651 ユーザー 0分0.916秒 システム 0分11秒578秒 実数 0分13秒098 ユーザー 0分0.939秒 システム 0分12秒004秒 実数 0分13秒586 ユーザー 0m1.024s システム 0分12秒372秒 実数 0分13秒026 ユーザー 0m0.976s システム 0分11秒910秒
平均時間: 12.962秒
ピーター・コーデスのコメントのベンチマーク結果
root@demo:~# 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 実数 0分14秒096 ユーザー 0分1.455秒 システム 0分12秒456秒 実数 0分14秒492 ユーザー 0分1.398秒 システム 0分12.897秒 実数 0分14秒309 ユーザー 0分1.518秒 システム 0分12.576秒 実数 0分14秒451 ユーザー 0分1.477秒 システム 0分12.776秒 実数 0分15秒101 ユーザー 0m1.554s システム 0分13秒378秒 実数 0分14秒223 ユーザー 0m1.470s システム 0分12.560秒 実数 0分14秒266 ユーザー 0分1.459秒 システム 0分12秒609秒 実数 0分14秒357 ユーザー 0分1.415秒 システム 0分12秒733秒 実数 0分14秒393 ユーザー 0m1.404s システム 0分12秒830秒 実数 0分14秒448 ユーザー 0分1.492秒 システム 0分12秒717秒
平均時間: 14.414秒
Fanatiqueの回答のベンチマーク結果
root@demo:~# 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 ; } ; 完了 実数 0分14秒561 ユーザー 0m1.991s システム 0分13秒343秒 実数 0分14秒521 ユーザー 0分1.958秒 システム 0分13秒352秒 実数 0分14秒696 ユーザー 0m1.967s システム 0分13秒463秒 実数 0分14秒562 ユーザー 0分1.875秒 システム 0分13秒400秒 実数 0分14秒609 ユーザー 0分1.841秒 システム 0分13秒533秒 実数 0分14秒892 ユーザー 0m2.050s システム 0分13秒630秒 実数 0分14秒291 ユーザー 0分1.885秒 システム 0分13秒182秒 実数 0分14秒843 ユーザー 0分2.066秒 システム 0分13秒578秒 実数 0分14秒219 ユーザー 0分1.837秒 システム 0分13秒145秒 実数 0分14秒503 ユーザー 0分1.803秒 システム 0分13秒419秒
平均時間: 14.570秒
harrymc の更新された回答のベンチマークの結果
root@demo:~# 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 実数 0分14秒975 ユーザー 0分1.728秒 システム 0分13秒050秒 実数 0分14秒710秒 ユーザー 0分1.586秒 システム 0分12秒979秒 実数 0分14秒644 ユーザー 0m1.641s システム 0分12.872秒 実数 0分14秒927 ユーザー 0m1.706s システム 0分13秒036秒 実数 0分14秒867 ユーザー 0m1.597s システム 0分13秒086秒 実数 0分15秒119 ユーザー 0分1.666秒 システム 0分13秒259秒 実数 0分14秒878 ユーザー 0m1.590s システム 0分13秒098秒 実数 0分14秒852 ユーザー 0m1.681s システム 0分13秒045秒 実数 0分14秒380秒 ユーザー 0分1.603秒 システム 0分12.663秒 実数 0分14秒558 ユーザー 0分1.514秒 システム 0分12秒899秒
平均時間: 14.791秒
harrymc の元の回答のベンチマークの結果
このコマンドは遅いため、ベンチマークは 1 回だけ実行しました。
root@demo:~# 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 実数 17分41秒926 ユーザー 12分26秒896秒 システム 4分58秒332
所要時間: 1061.926秒
答え4
ディレクトリが大きすぎて、含まれるファイルの数が多すぎる場合、@harrymc が示した元の方法は失敗します。
ファイルが多すぎる場合は、次のようfind
にパイプする必要があります。xargs
chmod
find /base/dir -type d -print0 | xargs -0 chmod 755
find /base/dir -type f -print0 | xargs -0 chmod 644