Questão Como recursivamente chmod todos os diretórios, exceto arquivos?


Como chmod 755 todos os diretórios, mas nenhum arquivo (recursivamente)?

Inversamente, como chmod apenas arquivos (recursivamente) mas nenhum diretório?


517


origem


Relacionado: Alterar todas as permissões de arquivos e pastas de um diretório para 644/755no SO - kenorb


Respostas:


Para dar recursivamente diretórios ler e executar privilégios:

find /path/to/base/dir -type d -exec chmod 755 {} +

Para dar recursivamente arquivos privilégios de leitura:

find /path/to/base/dir -type f -exec chmod 644 {} +

Ou, se houver muitos objetos para processar:

chmod 755 $(find /path/to/base/dir -type d)
chmod 644 $(find /path/to/base/dir -type f)

Ou, para reduzir chmod desova:

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

720



Os dois primeiros exemplos falham para diretórios com muitos arquivos: -bash: /bin/chmod: Argument list too long. O último comando funciona com muitos arquivos, mas ao usar sudo é preciso ter cuidado para colocá-lo antes xargs em vez de chmod: find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755 - Agargara
Também para notar, esses comandos são inclusivo do diretório base. Então, no exemplo acima, dir também será definido como 755. - CenterOrbit
chmod ... $(find /path/to/base/dir -type ...) falha para nomes de arquivos com espaços no nome. - Dan Dascalescu
Eu acho que a versão mais correta (mas não a mais rápida) em relação a espaços e símbolos em nomes de arquivos e número de arquivos é find /path/to/base/dir -type d -exec chmod 755 {} \; (find /path/to/base/dir -type f -exec chmod 644 {} \;). - Peter K


Uma razão comum para esse tipo de coisa é configurar diretórios para 755, mas arquivos para 644. Nesse caso, há uma maneira um pouco mais rápida que a de nik. find exemplo:

chmod -R u+rwX,go+rX,go-w /path

Significado:

  • -R = recursivamente;
  • u+rwX = Usuários podem ler, escrever e executar;
  • go+rX = grupo e outros podem ler e executar;
  • go-w = grupo e outros não podem escrever

O importante a notar aqui é que maiúsculas X age de forma diferente para minúsculas x. No manual, podemos ler:

Os bits de execução / pesquisa, se o arquivo for um diretório ou qualquer um dos bits de execução / pesquisa, estiver configurado no modo original (não modificado).

Em outras palavras, chmod u + X em um arquivo não irá definir o bit de execução; e g + X apenas o definirá se já estiver definido para o usuário.


261



-R = recursivamente; u + rwX = Os usuários podem ler, escrever e executar; go + rX = grupo e outros podem ler e executar; go-w = group e outros não podem escrever - släcker
Este padrão não corrigirá a situação quando alguém tiver feito chmod -R 777 desde o +X A opção não redefinirá os bits de execução existentes nos arquivos. Usar -x irá redefinir os diretórios e evitar que eles sejam inseridos. - Andrew Vit
@ ring0: Eu não estou pretendendo responder a pergunta literalmente como posada - nik já fez isso perfeitamente bem. Estou apontando uma solução mais barata para o caso mais comum. E sim, você obtém permissões diferentes para arquivos e diretórios com X, como explicado nos comentários. - bobince
go+rX,go-w -> go=rX não é? - Pierre de LESPINAY
Você também pode usar chmod u-x,u+X em combinação, etc., para remover os bits de execução dos arquivos, mas adicioná-los aos diretórios. - w0rp


Se você quiser ter certeza de que os arquivos estão configurados para 644 e existem arquivos no caminho que possuem o sinalizador de execução, você terá que remover o sinalizador de execução primeiro. + X não remove o sinalizador de execução dos arquivos que já o possuem.

Exemplo:

chmod -R ugo-x,u+rwX,go+rX,go-w path

Atualização: isso parece falhar porque a primeira alteração (ugo-x) torna o diretório impossível de ser executado, portanto, todos os arquivos abaixo dele não são alterados.


12



Isso funciona para mim e não vejo por que não. (Claro, se você fez apenas chmod -R ugo-x path, Aquilo pode ser um problema. Mas o comando completo fará o chmod u+rwX em cada diretório antes de tentar descer nele.) No entanto, acredito que chmod R u=rw,go=r,a+X path é suficiente - e é mais curto. - Scott
Eu achei isso funcionou corretamente; não houve problemas em inserir diretórios - Someone Somewhere


Eu decidi escrever um pequeno roteiro para isso eu mesmo.

Chmod script recursivo para dirs e / ou arquivos - Gist

Ele basicamente faz o chmod recursivo, mas também fornece um pouco de flexibilidade para as opções de linha de comando (define o diretório e / ou permissões de arquivo, ou exclui ambos, redefine tudo automaticamente para 755-644). Ele também verifica alguns cenários de erro.

Eu também escrevi sobre isso no meu blog.


4





Para dar recursivamente diretórios ler e executar privilégios:

find /path/to/base/dir -type d -exec chmod 755 {} \;

Para dar recursivamente arquivos privilégios de leitura:

find /path/to/base/dir -type f -exec chmod 644 {} \;

Mais tarde do que nunca, deixe-me atualizar a resposta de nik do lado da correção. Minha solução é mais lenta, mas funciona com qualquer número de arquivos, com quaisquer símbolos em nomes de arquivos, e você pode executá-lo normalmente com o sudo (mas cuidado para descobrir arquivos diferentes com o sudo).


3





Tente este script python; não requer nenhum desova de processos e faz apenas dois syscalls por arquivo. Além de uma implementação em C, ela provavelmente será a maneira mais rápida de fazer isso (eu precisei consertar um sistema de arquivos de 15 milhões de arquivos, todos em 777).

#!/usr/bin/python3
import os
for par, dirs, files in os.walk('.'):
    for d in dirs:
        os.chmod(par + '/' + d, 0o755)
    for f in files:
        os.chmod(par + '/' + f, 0o644)

No meu caso, um try / catch foi requerido em torno do último chmod, já que chmodding alguns arquivos especiais falharam.


0





Você também pode usar tree:

tree -faid /your_directory | xargs -L1 -I{} sudo chmod +x {}

-1





Você poderia usar o seguinte script bash como um exemplo. Certifique-se de dar permissões executáveis ​​(755). Simplesmente use ./autochmod.sh para o diretório atual, ou ./autochmod.sh <dir> para especificar um diferente.

#!/bin/bash

if [ -e $1 ]; then
    if [ -d $1 ];then
        dir=$1
    else
        echo "No such directory: $1"
        exit
    fi
else
    dir="./"
fi

for f in $(ls -l $dir | awk '{print $8}'); do
    if [ -d $f ];then
        chmod 755 $f
    else
        chmod 644 $f
    fi
done

-2



Uau! Tantos problemas! (1) Se $1 não é nulo, mas não é o nome de um diretório (por exemplo, é um erro de digitação), então dir fica definido para . sem mensagem. (2) $1 deveria estar "$1" e $dir deveria estar "$dir". (3) você não precisa dizer "./"; "." está bem (e, estritamente falando, você não precisa de citações aqui). (4) Esta não é uma solução recursiva. (5) no meu sistema, ls -l … | awk '{ print $8 }' Obtém os tempos de modificação dos arquivos. Você precisa { print $9 } para obter a primeira palavra de o nome do arquivo. E mesmo assim, (6) isso não lida com nomes de arquivos com espaço em branco. … - Scott
… E, por último, mas não menos importante (∞), se esse script estiver no diretório atual, ele será chmod  em si para 644, tornando-se assim não executável! - Scott