Я немного испортил резервное копирование своего личного каталога rsync
(возможно, потому что я делаю резервное копирование в файловой системе NTFS): все файлы здесь, но права доступа ко всем файлам и каталогам — 777. Мне было интересно, есть лимагияутилита, которая рекурсивно изменит:
- каталоги от 777 до 755.
- обычные файлы с 777 по 644. У меня дома не так много исполняемых файлов, поэтому я смогу сделать это вручную позже.
- оставьте остальные файлы (ссылки, что-либо еще?) без изменений.
Сделать это в скорлупе легко, но это займет несколько часов...
Дополнительный вопрос: есть ли какие-либо советы по правильному резервному копированию иерархии каталогов Linux на NTFS (с помощью 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, хотя беглое прочтение страницы руководства BSD для chmod позволяет предположить, что это так.долженработа там тоже.
решение3
Я провел сравнительный анализответ ситарама,Комментарий Питера Кордеса,Ответ Fanatique, иответ harrymc, ноэтот ответ имеет самый быстрый способ.
Средние значения:
- Ответ Делтика* – 7,480 секунд
* КредитПитер Кордесдляпредполагая параллелизм - Ответ ситарама – 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)" -ввести f -print0 | xargs -0 -P4 chmod 644 и подождать
Команда ситарама в формате бенчмарка:
chmod -R a=,u+rwX,go+rX "$(пароль)"
Команда Питера Кордеса в формате эталонного теста:
найти "$(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)" - тип d -exec chmod 755 {} + ; \ найти "$(pwd)" -тип f -exec chmod 644 {} +
Оригинальная команда harrymc в формате бенчмарка:
найти "$(pwd)" - тип d -exec chmod 755 {} \; ; \ найти "$(pwd)" -type f -exec chmod 644 {} \;
Моя команда была самой быстрой благодаря четырем параллельным chmod
процессам на тип файла. Это позволило запустить несколько ядер ЦП chmod
, что сместило узкое место в сторону потоков ввода-вывода ядра или диска.
Команда sitaram заняла второе место, потому что все делается в chmod
команде. Это существенно снижает накладные расходы по сравнению с другими ответами, потому что:
- Файлы необходимо сканировать только один раз (аналогично тому, как если бы вы делали одно сканирование
find
вместо двух) и - Не нужно создавать никаких дочерних процессов.
Однако эта команда является наименее гибкой, поскольку она основана на трюке, включающем различное значение исполняемого бита для обычных файлов и каталогов.
Комментарий Питера Кордеса, который использует одну find
команду, предотвращает двойной поиск записей каталога. Чем больше файлов, тем существеннее это улучшение. Он все еще имеет накладные расходы на создание дочерних chmod
процессов, поэтому он немного медленнее, чем chmod
решение -only.
Между командой Fanatique и обновленной командой harrymc, find
piped into xargs
( find | xargs
) был быстрее, поскольку поток результатов обрабатывается асинхронно. Вместо того, чтобы find
приостанавливать поведение поиска для -exec
, найденные результаты отправляются xargs
для параллельной обработки.
(Разделитель нулевого байта ( find -print0 | xargs -0
), похоже, не повлиял на время выполнения.)
Первоначальная команда harrymc была слишком медленной из-за накладных расходов на создание новой chmod
команды для каждого файла и папки, каждая из которых выполнялась последовательно.
В тестовой настройке имелось 1000002 обычных файла, содержащихся в 1001 каталоге:
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
перед chmod -R 0777 "$(pwd)"
запуском теста.
Представив OUTPUT
файл, содержащий выходные данные каждой команды бенчмарка, я рассчитал среднее время с помощью:
bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"
Результаты сравнительного анализа ответа Дельтика
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]- Завершено нахождение "$(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 реальные 0м8.005с пользователь 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 система 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с пользователь 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 система 0м23.728с [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с пользователь 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 секунд
Результаты бенчмарка ответа ситарама
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с пользователь 0m0.940s система 0м11.725с реальное 0м13.059с пользователь 0m0.896s система 0м11.937с реальное 0м12.819с пользователь 0m0.945s система 0m11.706s реальное 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с реальное 0м13.098с пользователь 0m0.939s система 0m12.004s реальное 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с пользователь 0m1.477s система 0m12.776s реальные 0м15.101с пользователь 0m1.554s система 0м13.378с реальное 0м14.223с пользователь 0м1.470с система 0м12.560с реальное 0м14.266с пользователь 0m1.459s система 0м12.609с реальное 0м14.357с пользователь 0м1.415с система 0m12.733s реальное 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} ; 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 реальное 0м14.561с пользователь 0m1.991s система 0м13.343с реальное 0м14.521с пользователь 0м1.958с система 0м13.352с реальное 0м14.696с пользователь 0m1.967s система 0m13.463s реальное 0м14.562с пользователь 0м1.875с система 0м13.400с реальное 0м14.609с пользователь 0m1.841s система 0м13.533с реальное 0м14.892с пользователь 0м2.050с система 0м13.630с реальное 0м14.291с пользователь 0м1.885с система 0м13.182с реальное 0м14.843с пользователь 0m2.066s система 0м13.578с реальное 0м14.219с пользователь 0m1.837s система 0м13.145с реальное 0м14.503с пользователь 0m1.803s система 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с пользователь 0m1.728s система 0м13.050с реальный 0м14.710с пользователь 0m1.586s система 0м12.979с реальное 0м14.644с пользователь 0m1.641s система 0m12.872s реальное 0м14.927с пользователь 0m1.706s система 0m13.036s реальное 0м14.867с пользователь 0м1.597с система 0м13.086с реальное 0м15.119с пользователь 0m1.666s система 0м13.259с реальное 0м14.878с пользователь 0м1.590с система 0м13.098с реальное 0м14.852с пользователь 0m1.681s система 0м13.045с реальный 0м14.380с пользователь 0m1.603s система 0m12.663s реальное 0м14.558с пользователь 0m1.514s система 0м12.899с
Среднее время: 14,791 секунды.
Результаты сравнительного анализа оригинального ответа harrymc
Из-за того, что эта команда была медленной, я запустил тест только один раз.
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