Linux ext4 備份/還原錯誤後還原檔案和目錄存取權限

Linux ext4 備份/還原錯誤後還原檔案和目錄存取權限

我有點搞砸了我的個人目錄的備份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暫停其查找行為。 (空字節分隔符號 ( ) 似乎不會影響運行時間。)-execxargs
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權限,就像問題的初始條件一樣。

然後,我對這些命令進行了十次基準測試,每次都在執行測試之前將權限還原為777with 。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傳輸:xargschmod

find /base/dir -type d -print0 | xargs -0 chmod 755 
find /base/dir -type f -print0 | xargs -0 chmod 644

相關內容