我搞砸了我的个人目录的备份rsync
(可能是因为我在 NTFS 文件系统上备份):所有文件都在这里,但所有文件和目录的访问权限都是 777。我想知道是否有魔法会递归改变的实用程序:
- 从 777 到 755 的目录。
- 常规文件从 777 到 644。我家里没有很多可执行文件,所以我可以稍后手动管理。
- 保持其他文件(链接,其他任何东西?)不变。
在 shell 中执行此操作很容易,但需要花费几个小时......
rsync
辅助问题:有没有什么建议可以在 NTFS(或其他)上正确备份 Linux 目录层次结构。
答案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 上,尽管粗略阅读 BSD 手册页的 chmod 表明它应该也在那里工作。
答案3
我进行了基准测试sitam 的回答,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 的命令(采用基准格式):
查找“$(pwd)”-type d-print0|xargs-0-P4 chmod 755&\ 找到“$(pwd)”-type f -print0 | xargs -0 -P4 chmod 644并等待
sitam 的命令,采用基准格式:
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
命令来防止目录条目的重复查找。文件越多,这种改进就越明显。它仍然有创建子进程的开销,这就是为什么它比-only 解决方案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:~# find | wc -l 1001003 root@demo:~# find -type d | wc -l 1001 root@demo:~# find -type f | wc -l 1000002
我将所有文件和文件夹设置为具有777
权限,就像问题的初始条件一样。
777
然后,我对这些命令进行了十次基准测试,每次都在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)" ; 时间 { find "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 & find "$(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秒 用户 0分2.536秒 系统 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秒 用户 0分2.636秒 系统 0分23.106秒 [1] 10021 [2] 10023 [1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755 [2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644 实际 0分8.005秒 用户 0分2.672秒 系统 0m24.557s [1] 10136 [2] 10138 [1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755 [2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644 实际 0 分 7.480 秒 用户 0分2.541秒 系统 0分23.699秒 [1] 10251 [2] 10253 [1]- 完成查找“$(pwd)”-type d | xargs -P4 chmod 755 [2]+ 完成查找“$(pwd)”-type f | xargs -P4 chmod 644 实际 0分7.397秒 用户 0分2.558秒 系统 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秒 用户 0分2.601秒 系统 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秒 用户 0分2.749秒 系统 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秒 用户 0分2.583秒 系统 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 秒 用户 0分2.640秒 系统 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 秒 用户 0分2.490秒 系统 0分22.943秒
平均时间:7.480秒
sitam 答案的基准测试结果
root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; time chmod -R a=,u+rwX,go+rX "$(pwd)" ; done 真实 0分12.860秒 用户 0分0.940秒 系统 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秒 用户 0分0.820秒 系统 0分11.834秒 实际 0分12.651秒 用户 0分0.916秒 系统 0分11.578秒 实际 0分13.098秒 用户 0分0.939秒 系统 0分12.004秒 实际 0分13.586秒 用户 0分1.024秒 系统 0分12.372秒 实际 0分13.026秒 用户 0分0.976秒 系统 0 分 11.910 秒
平均时间:12.962秒
Peter Cordes 评论的基准测试结果
root@demo:~# for i in {0..9} ; do chmod -R 0777 "$(pwd)" ; 时间查找 "$(pwd)" \( -type d -exec chmod 755 {} + \) -o \( -type f -exec chmod 644 {} + \) ; 完成 实际 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秒 用户 0分1.554秒 系统 0分13.378秒 实际 0分14.223秒 用户 0分1.470秒 系统 0 分 12.560 秒 实际 0分14.266秒 用户 0分1.459秒 系统 0 分 12.609 秒 实际 0分14.357秒 用户 0分1.415秒 系统 0 分 12.733 秒 实际 0分14.393秒 用户 0分1.404秒 系统 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)" ; 时间 { find "$(pwd)" -type d -print0 | xargs -0 chmod 755 ; find "$(pwd)" -type f -print0 | xargs -0 chmod 644 ; } ; 完成 实际 0分14.561秒 用户 0分1.991秒 系统 0分13.343秒 实际 0分14.521秒 用户 0分1.958秒 系统 0分13.352秒 实际 0分14.696秒 用户 0分1.967秒 系统 0分13.463秒 实际 0分14.562秒 用户 0分1.875秒 系统 0 分 13.400 秒 实际 0分14.609秒 用户 0分1.841秒 系统 0分13.533秒 实际 0分14.892秒 用户 0分2.050秒 系统 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)" ; 时间 { find "$(pwd)" -type d -exec chmod 755 {} + ; find "$(pwd)" -type f -exec chmod 644 {} + ; } ; 完成 实际 0分14.975秒 用户 0分1.728秒 系统 0 分 13.050 秒 实际 0分14.710秒 用户 0分1.586秒 系统 0分12.979秒 实际 0分14.644秒 用户 0分1.641秒 系统 0分12.872秒 实际 0分14.927秒 用户 0分1.706秒 系统 0分13.036秒 实际 0分14.867秒 用户 0分1.597秒 系统 0分13.086秒 实际 0分15.119秒 用户 0分1.666秒 系统 0分13.259秒 实际 0分14.878秒 用户 0分1.590秒 系统 0分13.098秒 实际 0分14.852秒 用户 0分1.681秒 系统 0分13.045秒 实际 0分14.380秒 用户 0分1.603秒 系统 0分12.663秒 实际 0分14.558秒 用户 0分1.514秒 系统 0分12.899秒
平均时间:14.791秒
harrymc 原始答案的基准测试结果
由于这个命令很慢,我只运行了一次基准测试。
root@demo:~# for i in {0..0} ; do chmod -R 0777 "$(pwd)" ; 时间 { find "$(pwd)" -type d -exec chmod 755 {} \; ; find "$(pwd)" -type f -exec chmod 644 {} \; ; } ; 完成 实际 17m41.926s 用户 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