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


Respostas:


802

Para dar recursivamente aos diretórios privilégios de leitura e execução:

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

Para dar recursivamente aos 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 a chmoddesova:

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

7
Os dois primeiros exemplos falhar por diretórios com muitos arquivos: -bash: /bin/chmod: Argument list too long. O último comando funciona com muitos arquivos, mas ao usar sudoum, deve-se ter o cuidado de colocá-lo antes do xargs em vez do chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara 7/17/17

2
Observe também que esses comandos incluem o diretório base. Portanto, no exemplo acima, dirtambém será definido como 755.
CenterOrbit

2
chmod ... $(find /path/to/base/dir -type ...)falha nos nomes de arquivos com espaços no nome.
Dan Dascalescu

7
Eu acho que a versão mais correta (mas não a mais rápida) em relação aos espaços e símbolos nos nomes de arquivos e no 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

Observe que isso só vai para a primeira camada que pode ler. Você precisará executá-lo várias vezes para se aprofundar na árvore de diretórios.
Henk Poley

290

Um motivo comum para esse tipo de coisa é definir diretórios para 755, mas arquivos para 644. Nesse caso, há uma maneira um pouco mais rápida que o findexemplo da nik :

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

Significado:

  • -R = recursivamente;
  • u+rwX = Os 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 ser observado aqui é que maiúsculas Xatuam de maneira 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 definido no modo original (não modificado).

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


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

23
Esse padrão não corrige a situação quando alguém o fez, chmod -R 777pois a +Xopção não redefinirá os bits de execução existentes nos arquivos. O uso de -x redefinirá os diretórios e evitará a descida neles.
Andrew Vit

3
@ ring0: Não pretendo responder a pergunta literalmente, como colocado - a nik já fez isso perfeitamente. 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 X, conforme explicado nos comentários.
quer

6
go+rX,go-w-> go=rXnão é?
Pierre de LESPINAY

5
Você também pode usar chmod u-x,u+Xem combinação, etc., para remover bits de execução de arquivos, mas adicioná-los aos diretórios.
W0rp

14

Se você deseja garantir que os arquivos estejam configurados para 644 e que existam arquivos no caminho que possuem o sinalizador de execução, será necessário 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 não executável, para que todos os arquivos abaixo dele não sejam alterados.


1
Isso funciona para mim e não vejo por que não funcionaria. (Claro, se você fez exatamente chmod -R ugo-x pathisso, isso pode ser um problema. Mas o comando completo fará o comando chmod u+rwXem cada diretório antes de tentar descer para ele.) No entanto, acredito que isso chmod R u=rw,go=r,a+X pathé suficiente - e é mais curto.
Scott

Eu achei que isso funcionou corretamente; não houve problemas com diretórios que entram
alguém em algum lugar

4

Decidi escrever um pequeno roteiro para isso.

Script chmod recursivo para dirs e / ou arquivos - Gist :

chmodr.sh

#!/bin/sh
# 
# chmodr.sh
#
# author: Francis Byrne
# date: 2011/02/12
#
# Generic Script for recursively setting permissions for directories and files
# to defined or default permissions using chmod.
#
# Takes a path to recurse through and options for specifying directory and/or 
# file permissions.
# Outputs a list of affected directories and files.
# 
# If no options are specified, it recursively resets all directory and file
# permissions to the default for most OSs (dirs: 755, files: 644).

# Usage message
usage()
{
  echo "Usage: $0 PATH -d DIRPERMS -f FILEPERMS"
  echo "Arguments:"
  echo "PATH: path to the root directory you wish to modify permissions for"
  echo "Options:"
  echo " -d DIRPERMS, directory permissions"
  echo " -f FILEPERMS, file permissions"
  exit 1
}

# Check if user entered arguments
if [ $# -lt 1 ] ; then
 usage
fi

# Get options
while getopts d:f: opt
do
  case "$opt" in
    d) DIRPERMS="$OPTARG";;
    f) FILEPERMS="$OPTARG";;
    \?) usage;;
  esac
done

# Shift option index so that $1 now refers to the first argument
shift $(($OPTIND - 1))

# Default directory and file permissions, if not set on command line
if [ -z "$DIRPERMS" ] && [ -z "$FILEPERMS" ] ; then
  DIRPERMS=755
  FILEPERMS=644
fi

# Set the root path to be the argument entered by the user
ROOT=$1

# Check if the root path is a valid directory
if [ ! -d $ROOT ] ; then
 echo "$ROOT does not exist or isn't a directory!" ; exit 1
fi

# Recursively set directory/file permissions based on the permission variables
if [ -n "$DIRPERMS" ] ; then
  find $ROOT -type d -print0 | xargs -0 chmod -v $DIRPERMS
fi

if [ -n "$FILEPERMS" ] ; then
  find $ROOT -type f -print0 | xargs -0 chmod -v $FILEPERMS
fi

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

Eu também escrevi sobre isso no meu blog .


2

Para dar recursivamente aos diretórios privilégios de leitura e execução:

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

Para dar recursivamente aos arquivos privilégios de leitura:

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

Antes 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 símbolos nos nomes de arquivos, e você pode executá-la com o sudo normalmente (mas lembre-se de que ele poderá descobrir arquivos diferentes com o sudo).


Este é um rebaixamento da resposta de nik . Por que você acredita que há algo errado com a resposta de nik?
975 Scott

@ Scott, a resposta da nik falha com um grande número de arquivos.
Peter K

Tenho 99% de certeza de que você está enganado. Você pode fornecer alguma evidência para apoiar sua reivindicação?
25318 Scott

Sim, parece que estou errado mesmo. find ... + parece quebrar a linha em vários comandos, boa captura!
Peter K

0

Experimente este script python; ele não requer geração de processos e faz apenas dois syscalls por arquivo. Além de uma implementação em C, provavelmente será a maneira mais rápida de fazê-lo (eu precisava corrigir um sistema de arquivos de 15 milhões de arquivos, todos definidos como 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, foi necessário um try / catch em torno do último chmod, pois o chmodding alguns arquivos especiais falhou.


-1

Você também pode usar tree:

tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 "$1"' -- '{}'

e se você quiser ver também a pasta, adicione um eco

 tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 "$1" && echo$1' -- '{}'

@ Scott 1) ​​Você está certo sobre + x mudei para 755; 2) 3) para resolver isso, coloquei o espaço reservado entre aspas simples como este '{}'
Eduard Florinescu 10/10

@ Scott Concordo que esta não é a melhor resposta também é lenta, mas deixará aqui para fins "didáticos" e os comentários vão explicar mais, também as pessoas podem aprender sobre xargsquestões. Aspas simples em nomes de arquivos são eles próprios um problema para muitos comandos e roteiro que é por isso que eu listados todos os arquivos que contêm aspas simples e removidos-los (as aspas quero dizer)
Eduard Florinescu

@ Scott Em meus sistemas eu procurei por todos os arquivos que continham aspas simples e substituídas as aspas simples
Eduard Florinescu

@ Scott Como você resolveria o fato de o xargs não resolver corretamente as aspas simples?
Eduard Florinescu 10/10


-2

Você pode usar o seguinte script bash como exemplo. Certifique-se de fornecer permissões executáveis ​​(755). Simplesmente use ./autochmod.sh para o diretório atual ou ./autochmod.sh <dir> para especificar um diretório 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 $1não for nulo, mas não for o nome de um diretório (por exemplo, é um erro de digitação), dirserá definido como .sem mensagem. (2) $1deve ser "$1"e $dirdeve ser "$dir". (3) Você não precisa dizer "./"; "."é bom (e, estritamente falando, você não precisa de aspas 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 }obter a primeira palavra do nome do arquivo. E mesmo assim, (6) isso não trata nomes de arquivos com espaço em branco. ...
Scott

1
... E, por último mas não menos importante (∞), se este script está no diretório atual, ele vai chmod -se para 644, tornando-se assim não executável!
7767 Scott
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.