Eu meio que estraguei o backup do meu diretório pessoal rsync
(talvez porque estou fazendo backup em um sistema de arquivos NTFS): todos os arquivos estão aqui, mas todos os direitos de acesso a arquivos e diretórios são 777. Eu queria saber se havia umMagiautilitário que mudaria recursivamente:
- os diretórios de 777 a 755.
- os arquivos normais de 777 a 644. Não tenho muitos executáveis em minha casa, então posso gerenciar isso manualmente mais tarde.
- deixe outros arquivos (links, mais alguma coisa?) Inalterados.
Fazer isso com casca é fácil, mas levará horas...
Pergunta subsidiária: algum conselho para fazer backup adequadamente de uma hierarquia de diretórios Linux em NTFS (com rsync
ou outro).
Responder1
A solução padrão recomendada é direta:
find . -type d -exec chmod 0755 "{}" \+
find . -type f -exec chmod 0644 "{}" \+
Isso acrescentará tantos nomes de arquivos quanto possível como argumentos a um único comando, até o comprimento máximo da linha de comando do sistema. Se a linha exceder esse comprimento, o comando será chamado várias vezes.
Se quiser chamar o comando uma vez por arquivo, você pode fazer:
find . -type d -exec chmod 0755 "{}" \;
find . -type f -exec chmod 0644 "{}" \;
Responder2
chmod -R a=,u+rwX,go+rX $DIR
parece funcionar bem e é muito provável que seja o mais rápido, independentemente de como você olha para ele.
(Eu verifiquei com strace
, e isso faz apenasum fchmodat()
syscall por arquivo/diretório - para arquivos com 644 e para diretórios com 755).
O truque é a X
permissão, documentada em man chmod
, que funciona x
apenas para diretórios - a mesma distinção que você queria.
O que énãodocumentado é meu palpite de que eles seriam aplicados na mesma sequência em que são especificados, e não apenas em alguma ordem aleatória, mas testes repetidos com diversas variantes me convenceram de que eles realmente são executados na ordem dada, então tenho certeza isso sempre vai funcionar assim.
Devo mencionar que isso ocorre no Linux, embora uma leitura superficial da página de manual do BSD para chmod sugira quedevetrabalhar lá também.
Responder3
Eu compareiresposta do sitaram,Comentário de Peter Cordes,Resposta do Fanático, eresposta de harrymc, masesta resposta tem o caminho mais rápido.
Médias:
- Resposta de Deltik* – 7.480 segundos
* Crédito paraPedro Cordesparasugerindo paralelismo - resposta do sitaram – 12,962 segundos (73,275% mais lento que o melhor)
- Comentário de Peter Cordes – 14,414 segundos (92,685% mais lento que o melhor)
- Resposta de Fanatique – 14,570 segundos (94,772% mais lento que o melhor)
- resposta atualizada de harrymc – 14,791 segundos (97,730% mais lento que o melhor)
- resposta original de harrymc – 1.061,926 segundos (14.096,113% mais lento que o melhor)
Resumo estatístico completo:
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
Comando do Deltik, em formato de benchmark:
encontre "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 &\ encontre "$(pwd)" -type f -print0 | xargs -0 -P4 chmod 644 e espere
Comando do sitaram, em formato de benchmark:
chmod -R a=,u+rwX,go+rX "$(pwd)"
Comando de Peter Cordes, em formato de benchmark:
encontre "$(pwd)" \( -type d -exec chmod 755 {} + \) \ -o \( -type f -exec chmod 644 {} + \)
Comando do Fanatique, em formato de benchmark:
encontre "$(pwd)" -type d -print0 | xargs -0 chmod 755; \ encontre "$(pwd)" -type f -print0 | xargs -0 chmod 644
Comando atualizado de harrymc, em formato de benchmark:
encontre "$(pwd)" -type d -exec chmod 755 {} + ; \ encontre "$(pwd)" -type f -exec chmod 644 {} +
Comando original de harrymc, em formato de benchmark:
encontre "$(pwd)" -type d -exec chmod 755 {} \; ; \ encontre "$(pwd)" -type f -exec chmod 644 {} \;
Meu comando foi o mais rápido graças aos quatro chmod
processos paralelos por tipo de arquivo. Isso permitiu a execução de vários núcleos de CPU chmod
, o que move o gargalo para os threads de E/S do kernel ou para o disco.
O comando do sitaram foi o vice-campeão porque tudo é feito dentro do chmod
comando. Isso reduz substancialmente a sobrecarga em comparação com as outras respostas porque:
- Os arquivos só precisam ser verificados uma vez (semelhante a fazer um
find
em vez de dois) e - Nenhum processo filho precisa ser criado.
Este comando é o menos flexível, entretanto, porque se baseia em um truque que envolve o significado diferente do bit executável entre arquivos e diretórios regulares.
O comentário de Peter Cordes, que usa um find
comando, evita pesquisas duplas de entradas de diretório. Quanto mais arquivos houver, mais substancial será essa melhoria. Ele ainda tem a sobrecarga de criação chmod
de processos filhos, e é por isso que é um pouco mais lento que a chmod
solução -only.
Entre o comando do Fanatique e o comando atualizado do harrymc, find
a canalização para xargs
( find | xargs
) foi mais rápida porque o fluxo de resultados é processado de forma assíncrona. Em vez de find
pausar seu comportamento de localização para -exec
, os resultados encontrados são enviados xargs
para processamento simultâneo.
(O delimitador de byte nulo ( find -print0 | xargs -0
) não parece afetar o tempo de execução.)
O comando original de harrymc era muito lento devido à sobrecarga de um novo chmod
comando para cada arquivo e pasta, cada um executado em sequência.
Na configuração de teste, havia 1.000.002 arquivos regulares contidos em 1.001 diretórios:
root@demo:~# echo {0..999} | xargs mkdir-p root@demo:~# find -type d -exec bash -c "cd {}; echo {0..999} | xargs touch" \; root@demo:~# encontrar | wc-l 1001003 root@demo:~# find -type d | wc-l 1001 root@demo:~# find -type f | wc-l 1000002
Defino todos os arquivos e pastas para terem 777
permissões, conforme as condições iniciais da pergunta.
Em seguida, comparei os comandos dez vezes, cada vez restaurando as permissões 777
antes chmod -R 0777 "$(pwd)"
de executar o teste.
Representando OUTPUT
um arquivo que contém a saída de cada comando de benchmark, calculei o tempo médio usando:
bc <<< "scale=3; ($(grep real OUTPUT | grep -Po '(?<=m).*(?=s)' | xargs | sed 's/ /+/g'))/10"
Resultados do benchmark da resposta da Deltik
root@demo:~# for i in {0..9} ; faça chmod -R 0777 "$(pwd)"; tempo {encontre "$(pwd)" -type d -print0 | xargs -0 -P4 chmod 755 e encontre "$(pwd)" -type f -print0 | xargs -0 -P4 chmod 644 & espere; } ; feito [1] 9791 [2] 9793 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.634s reais usuário 0m2.536s sistema 0m23.384s [1] 9906 [2] 9908 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.443s reais usuário 0m2.636s sistema 0m23.106s [1] 10021 [2] 10023 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m8.005s reais usuário 0m2.672s sistema 0m24.557s [1] 10136 [2] 10138 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.480s reais usuário 0m2.541s sistema 0m23.699s [1] 10251 [2] 10253 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.397s reais usuário 0m2.558s sistema 0m23.583s [1] 10366 [2] 10368 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.482s reais usuário 0m2.601s sistema 0m23.728s [1] 10481 [2] 10483 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.679s reais usuário 0m2.749s sistema 0m23.395s [1] 10596 [2] 10598 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.243s reais usuário 0m2.583s sistema 0m23.400s [1] 10729 [2] 10731 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.320s reais usuário 0m2.640s sistema 0m23.403s [1] 10844 [2] 10847 [1]- Concluído, encontre "$(pwd)" -type d | xargs -P4 chmod 755 [2]+ Concluído, encontre "$(pwd)" -type f | xargs -P4 chmod 644 0m7.121s reais usuário 0m2.490s sistema 0m22.943s
Tempo médio: 7.480 segundos
Resultados do benchmark da resposta do sitaram
root@demo:~# for i in {0..9} ; faça chmod -R 0777 "$(pwd)"; tempo chmod -R a=,u+rwX,go+rX "$(pwd)" ; feito 0m12.860s reais usuário 0m0.940s sistema 0m11.725s reais 0m13.059s usuário 0m0.896s sistema 0m11.937s 0m12.819s reais usuário 0m0.945s sistema 0m11.706s reais 0m13.078s usuário 0m0.855s sistema 0m12.000s 0m12.653s reais usuário 0m0.856s sistema 0m11.667s 0m12.787s reais usuário 0m0.820s sistema 0m11.834s 0m12.651s reais usuário 0m0.916s sistema 0m11.578s reais 0m13.098s usuário 0m0.939s sistema 0m12.004s reais 0m13.586s usuário 0m1.024s sistema 0m12.372s reais 0m13.026s usuário 0m0.976s sistema 0m11.910s
Tempo médio: 12,962 segundos
Resultados do benchmark do comentário de Peter Cordes
root@demo:~# for i in {0..9} ; faça chmod -R 0777 "$(pwd)"; hora encontrar "$(pwd)" \( -type d -exec chmod 755 {} + \) -o \( -type f -exec chmod 644 {} + \) ; feito reais 0m14.096s usuário 0m1.455s sistema 0m12.456s 0m14.492s reais usuário 0m1.398s sistema 0m12.897s 0m14.309s reais usuário 0m1.518s sistema 0m12.576s 0m14.451s reais usuário 0m1.477s sistema 0m12.776s 0m15.101s reais usuário 0m1.554s sistema 0m13.378s 0m14.223s reais usuário 0m1.470s sistema 0m12.560s 0m14.266s reais usuário 0m1.459s sistema 0m12.609s 0m14.357s reais usuário 0m1.415s sistema 0m12.733s 0m14.393s reais usuário 0m1.404s sistema 0m12.830s 0m14.448s reais usuário 0m1.492s sistema 0m12.717s
Tempo médio: 14,414 segundos
Resultados do benchmark da resposta do Fanatique
root@demo:~# for i in {0..9} ; faça chmod -R 0777 "$(pwd)"; tempo {encontre "$(pwd)" -type d -print0 | xargs -0 chmod 755; encontre "$(pwd)" -type f -print0 | xargs -0 chmod 644; } ; feito 0m14.561s reais usuário 0m1.991s sistema 0m13.343s 0m14.521s reais usuário 0m1.958s sistema 0m13.352s 0m14.696s reais usuário 0m1.967s sistema 0m13.463s reais 0m14.562s usuário 0m1.875s sistema 0m13.400s 0m14.609s reais usuário 0m1.841s sistema 0m13.533s 0m14.892s reais usuário 0m2.050s sistema 0m13.630s 0m14.291s reais usuário 0m1.885s sistema 0m13.182s 0m14.843s reais usuário 0m2.066s sistema 0m13.578s 0m14.219s reais usuário 0m1.837s sistema 0m13.145s 0m14.503s reais usuário 0m1.803s sistema 0m13.419s
Tempo médio: 14.570 segundos
Resultados do benchmark da resposta atualizada de harrymc
root@demo:~# for i in {0..9} ; faça chmod -R 0777 "$(pwd)"; tempo {encontre "$(pwd)" -type d -exec chmod 755 {} + ; encontre "$(pwd)" -type f -exec chmod 644 {} + ; } ; feito 0m14.975s reais usuário 0m1.728s sistema 0m13.050s 0m14.710s reais usuário 0m1.586s sistema 0m12.979s 0m14.644s reais usuário 0m1.641s sistema 0m12.872s 0m14.927s reais usuário 0m1.706s sistema 0m13.036s 0m14.867s reais usuário 0m1.597s sistema 0m13.086s 0m15.119s reais usuário 0m1.666s sistema 0m13.259s 0m14.878s reais usuário 0m1.590s sistema 0m13.098s 0m14.852s reais usuário 0m1.681s sistema 0m13.045s 0m14.380s reais usuário 0m1.603s sistema 0m12.663s 0m14.558s reais usuário 0m1.514s sistema 0m12.899s
Tempo médio: 14,791 segundos
Resultados do benchmark da resposta original de Harrymc
Devido à lentidão desse comando, executei o benchmark apenas uma vez.
root@demo:~# for i in {0..0} ; faça chmod -R 0777 "$(pwd)"; tempo {encontre "$(pwd)" -type d -exec chmod 755 {} \; ; encontre "$(pwd)" -type f -exec chmod 644 {} \; ; } ; feito 17m41.926s reais usuário 12m26.896s sistema 4m58.332s
Tempo gasto: 1.061,926 segundos
Responder4
Se os diretórios forem muito grandes e contiverem muitos arquivos, a maneira original que @harrymc mostrou irá falhar.
Se você tiver muitos arquivos, precisará find
canalizar xargs
:chmod
find /base/dir -type d -print0 | xargs -0 chmod 755
find /base/dir -type f -print0 | xargs -0 chmod 644