我有點搞砸了我的個人目錄的備份rsync
(也許是因為我在 NTFS 檔案系統上備份):所有檔案都在這裡,但所有檔案和目錄存取權限都是 777。魔法會遞歸改變的實用程式:
- 從 777 到 755 的目錄。
- 從 777 到 644 的常規文件。
- 保留其他文件(鏈接,還有其他東西嗎?)不變。
在 shell 中執行此操作很容易,但需要幾個小時...
附屬問題:關於在 NTFS 上正確備份 Linux 目錄層次結構(使用rsync
或其他)的任何建議。
答案1
標準推薦的解決方案很簡單:
find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+
這會將盡可能多的檔案名稱作為參數附加到單一命令,直到系統的最大命令列長度。如果該行超過此長度,則該命令將被多次呼叫。
如果您想每個檔案調用一次該命令,您可以這樣做:
find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;
答案2
chmod -R a=,u+rwX,go+rX $DIR
似乎工作得很好,而且很可能是最快的,無論你怎麼看。
(我檢查過strace
,它只使一 fchmodat()
每個檔案/目錄的系統呼叫-對於 644 的檔案和 755 的目錄)。
訣竅在於X
權限,記錄在 中man chmod
,它的作用類似於x
僅針對目錄——這正是您想要的區別。
什麼是不是記錄的是我的猜測,它們將按照指定的相同順序應用,而不僅僅是以某種隨機順序,但是對幾個變體的重複測試使我相信它們確實按照給定的順序運行,所以我很確定這總是會這樣進行。
我應該提到這是在 Linux 上,儘管粗略地閱讀了 chmod 的 BSD 手冊頁表明它應該也在那裡工作。
答案3
我進行了基準測試西塔拉姆的回答,彼得·科德斯的評論,法納蒂克的回答, 和哈利麥克的回答, 但這個答案有最快的方法。
平均值:
- 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 的命令,採用基準格式:
尋找“$(pwd)”-type d -print0 | xargs -0 -P4 chmod 755 & \ 尋找“$(pwd)”-type f -print0 | xargs -0 -P4 chmod 644 & 等待
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 {} \;
由於chmod
每種文件類型有四個並行進程,我的命令是最快的。這允許多個 CPU 核心運行chmod
,從而將瓶頸移向核心 I/O 執行緒或磁碟。
Sitaram 的命令獲得亞軍,因為一切都在該chmod
命令內完成。與其他答案相比,這大大減少了開銷,因為:
- 文件只需掃描一次(類似於掃描一次
find
而不是兩次),並且 - 不需要建立子進程。
然而,這個命令是最不靈活的,因為它依賴於涉及常規文件和目錄之間可執行位的不同含義的技巧。
Peter Cordes 的評論使用一個find
命令來防止目錄條目的雙重查找。文件越多,這種改進就越顯著。它仍然有創建子進程的開銷chmod
,這就是為什麼它比唯一的解決方案慢得多的原因chmod
。
在 Fanatique 的命令和 harrymc 的更新命令之間,find
透過管道傳輸到xargs
( find | xargs
) 的速度更快,因為結果流是非同步處理的。找到的結果將被發送到並發處理, 而不是find
暫停其查找行為。 (空字節分隔符號 ( ) 似乎不會影響運行時間。)-exec
xargs
find -print0 | xargs -0
harrymc 的原始命令太慢,因為chmod
每個檔案和資料夾都按順序執行新命令的開銷。
在測試設定中,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:~# 查找 |廁所-l 1001003 root@demo:~# find -type d |廁所-l 1001 root@demo:~# find -type f |廁所-l 1000002
我將所有文件和資料夾設定為具有777
權限,就像問題的初始條件一樣。
然後,我對這些命令進行了十次基準測試,每次都在執行測試之前將權限還原為777
with 。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} ;執行 chmod -R 0777 "$(pwd)" ;時間 { 尋找“$(pwd)” -type d -print0 | xargs -0 -P4 chmod 755 & 找「$(pwd)」 -type f -print0 | xargs -0 -P4 chmod 644 & 等待; };完畢 [1]9791 [2]9793 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.634秒 用戶0m2.536s 系統0米23.384秒 [1]9906 [2]9908 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.443秒 用戶0m2.636s 系統0米23.106秒 [1]10021 [2]10023 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0m8.005s 用戶0m2.672s 系統0米24.557秒 [1]10136 [2]10138 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.480秒 用戶0m2.541s 系統 0m23.699s [1]10251 [2]10253 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.397秒 用戶0m2.558s 系統0米23.583秒 [1]10366 [2]10368 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.482秒 用戶0m2.601s 系統 0m23.728s [1]10481 [2]10483 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.679秒 用戶0m2.749s 系統0米23.395秒 [1]10596 [2]10598 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.243秒 用戶0m2.583s 系統0米23.400秒 [1]10729 [2]10731 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.320秒 用戶0m2.640s 系統0米23.403秒 [1]10844 [2]10847 [1]- 完成找出「$(pwd)」-type d | xargs -P4 chmod 755 [2]+ 完成找「$(pwd)」-type f | xargs -P4 chmod 644 真實0米7.121秒 用戶0m2.490s 系統0米22.943秒
平均時間:7.480秒
Sitaram 答案的基準測試結果
root@demo:~# for i in {0..9} ;執行 chmod -R 0777 "$(pwd)" ;時間 chmod -R a=,u+rwX,go+rX "$(pwd)" ;完畢 真實0米12.860秒 用戶0分0.940秒 系統0分11.725秒 真實0米13.059秒 用戶0m0.896s 系統 0m11.937s 真實0米12.819秒 用戶0m0.945s 系統0分11.706秒 真實0米13.078秒 用戶0m0.855s 系統0分12.000秒 真實0公尺12.653秒 用戶0m0.856s 系統 0m11.667s 真實0米12.787秒 用戶0m0.820s 系統 0m11.834s 真實0公尺12.651秒 用戶0m0.916s 系統0分11.578秒 真實0m13.098s 用戶0m0.939s 系統0m12.004s 真實0米13.586秒 用戶0m1.024s 系統0分12.372秒 真實0米13.026秒 用戶0m0.976s 系統0分11分910秒
平均時間:12.962秒
Peter Cordes 評論的基準測試結果
root@demo:~# for i in {0..9} ;執行 chmod -R 0777 "$(pwd)" ; time find "$(pwd)" \( -type d -exec chmod 755 {} + \) -o \( -type f -exec chmod 644 {} + \) ;完畢 真 0m14.096s 用戶0m1.455s 系統0米12.456秒 真實0公尺14.492秒 用戶0m1.398s 系統 0m12.897s 真實0分14.309秒 用戶0m1.518s 系統0米12.576秒 真實0米14.451秒 用戶0m1.477s 系統0米12.776秒 真實0公尺15.101秒 用戶0m1.554s 系統0分13.378秒 真實0分14.223秒 用戶0m1.470s 系統0分12.560秒 真實0公尺14.266秒 用戶0m1.459s 系統 0m12.609s 真實0米14.357秒 用戶0m1.415s 系統0分12.733秒 真實0分14.393秒 用戶0m1.404s 系統0分12.830秒 真實0米14.448秒 用戶0m1.492s 系統0分12.717秒
平均時間:14.414秒
Fanatique 答案的基準測試結果
root@demo:~# for i in {0..9} ;執行 chmod -R 0777 "$(pwd)" ;時間 { 尋找“$(pwd)” -type d -print0 | xargs -0 chmod 755 ;尋找“$(pwd)”-type f -print0 | xargs -0 chmod 644 ; };完畢 真實0公尺14.561秒 用戶0m1.991s 系統0分13.343秒 真實0米14.521秒 用戶0m1.958s 系統0分13.352秒 真實0公尺14.696秒 用戶0m1.967s 系統0分13.463秒 真實0米14.562秒 用戶0m1.875s 系統0分13.400秒 真實0公尺14.609秒 用戶0m1.841s 系統0分13.533秒 真實0公尺14.892秒 用戶0m2.050s 系統0分13.630秒 真實0公尺14.291秒 用戶0m1.885s 系統0分13.182秒 真實0米14.843秒 用戶0m2.066s 系統0分13.578秒 真實0分14.219秒 用戶0m1.837s 系統0分13.145秒 真實0米14.503秒 用戶0m1.803s 系統 0m13.419s
平均時間:14.570 秒
harrymc 更新答案的基準測試結果
root@demo:~# for i in {0..9} ;執行 chmod -R 0777 "$(pwd)" ;時間 { find "$(pwd)" -type d -exec chmod 755 {} + ;求“$(pwd)”-type f -exec chmod 644 {} + ; };完畢 真實0米14.975秒 用戶0m1.728s 系統0分13.050秒 真實0米14.710秒 用戶0m1.586s 系統 0m12.979s 真實0米14.644秒 用戶0m1.641s 系統 0m12.872s 真實0米14.927秒 用戶0m1.706s 系統0m13.036s 真實0米14.867秒 用戶0m1.597s 系統0m13.086s 真實0公尺15.119秒 用戶0m1.666s 系統0分13.259秒 真實0米14.878秒 用戶0m1.590s 系統0m13.098s 真實0米14.852秒 用戶0m1.681s 系統 0m13.045s 真實0米14.380秒 用戶0m1.603s 系統0分12.663秒 真實0米14.558秒 用戶0m1.514s 系統 0m12.899s
平均時間:14.791秒
harrymc 原始答案的基準測試結果
由於這個命令太慢,我只運行了一次基準測試。
root@demo:~# for i in {0..0} ;執行 chmod -R 0777 "$(pwd)" ; time { find "$(pwd)" -type d -exec chmod 755 {} \; ;找出“$(pwd)”-type f -exec chmod 644 {} \; ; };完畢 真實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