¿Cómo recursivamente chmod todos los directorios excepto los archivos?

Respuestas:

802

Para otorgar recursivamente a los directorios privilegios de lectura y ejecución:

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

Para otorgar recursivamente privilegios de lectura de archivos :

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

O, si hay muchos objetos para procesar:

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

O, para reducir el chmoddesove:

find /path/to/base/dir -type d -print0 | xargs -0 chmod 755 
find /path/to/base/dir -type f -print0 | xargs -0 chmod 644
nik
fuente
77
Los dos primeros ejemplos fallan para los directorios con demasiados archivos: -bash: /bin/chmod: Argument list too long. El último comando funciona con muchos archivos, pero al usar sudouno debe tener cuidado de ponerlo antes de xargs en lugar de chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara
2
También para tener en cuenta, estos comandos incluyen el directorio base. Entonces, en el ejemplo anterior, dirtambién se establecerá en 755.
CenterOrbit
2
chmod ... $(find /path/to/base/dir -type ...)falla para nombres de archivos con espacios en el nombre.
Dan Dascalescu
77
Creo que la versión más correcta (pero no la más rápida) con respecto a los espacios y símbolos en los nombres de archivos y la cantidad de archivos es find /path/to/base/dir -type d -exec chmod 755 {} \;( find /path/to/base/dir -type f -exec chmod 644 {} \;).
Peter K
Tenga en cuenta que esto solo va a la primera capa que puede leer. Tendrá que ejecutarlo varias veces para profundizar en el árbol de directorios.
Henk Poley
290

Una razón común para este tipo de cosas es establecer directorios en 755 pero archivos en 644. En este caso, hay una forma un poco más rápida que el findejemplo de Nik :

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

Sentido:

  • -R = recursivamente;
  • u+rwX = Los usuarios pueden leer, escribir y ejecutar;
  • go+rX = grupo y otros pueden leer y ejecutar;
  • go-w = grupo y otros no pueden escribir

Lo importante a tener en cuenta aquí es que las mayúsculas Xactúan de manera diferente a las minúsculas x. En el manual podemos leer:

Los bits de ejecución / búsqueda si el archivo es un directorio o alguno de los bits de ejecución / búsqueda se configuran en el modo original (sin modificar).

En otras palabras, chmod u + X en un archivo no establecerá el bit de ejecución; y g + X solo lo configurará si ya está configurado para el usuario.

bobince
fuente
55
-R = recursivamente; u + rwX = Los usuarios pueden leer, escribir y ejecutar; go + rX = group y otros pueden leer y ejecutar; go-w = group y otros no pueden escribir
släcker
23
Este patrón no solucionará la situación cuando alguien lo haya hecho, chmod -R 777ya que la +Xopción no restablecerá los bits de ejecución existentes en los archivos. El uso de -x restablecerá los directorios y evitará descender a ellos.
Andrew Vit el
3
@ ring0: No tengo la intención de responder la pregunta literalmente como se plantea, nik ya lo ha hecho perfectamente bien. Estoy señalando una solución más barata para el caso más común. Y sí, obtienes diferentes permisos para archivos y directorios con X, como se explica en los comentarios.
bobince
66
go+rX,go-w-> go=rX¿no es así?
Pierre de LESPINAY
55
También puede usar chmod u-x,u+Xen combinación, etc., para eliminar bits de ejecución para archivos, pero agregarlos para directorios.
w0rp
14

Si desea asegurarse de que los archivos estén configurados en 644 y que haya archivos en la ruta que tengan el indicador de ejecución, primero deberá eliminar el indicador de ejecución. + X no elimina el indicador de ejecución de los archivos que ya lo tienen.

Ejemplo:

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

Actualización: esto parece fallar porque el primer cambio (ugo-x) hace que el directorio sea ejecutable, por lo que no se cambian todos los archivos debajo.

mpolden
fuente
1
Esto funciona para mí, y no veo por qué no lo haría. (Claro, si lo hiciste chmod -R ugo-x path, eso podría ser un problema. Pero el comando completo lo hará chmod u+rwXen cada directorio antes de intentar descender a él). Sin embargo, creo que eso chmod R u=rw,go=r,a+X pathes suficiente, y es más corto.
Scott
Encontré que esto funcionó correctamente; no hubo problemas al ingresar directorios
alguien en algún lugar el
4

Decidí escribir un pequeño guión para esto yo mismo.

Script chmod recursivo para directorios y / o archivos - 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

Básicamente realiza el chmod recursivo, pero también proporciona un poco de flexibilidad para las opciones de línea de comandos (establece los permisos de directorio y / o archivo, o excluye ambos, restablece automáticamente todo a 755-644). También comprueba algunos escenarios de error.

También escribí sobre eso en mi blog .

francisbyrne
fuente
2

Para otorgar recursivamente a los directorios privilegios de lectura y ejecución:

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

Para otorgar recursivamente privilegios de lectura de archivos :

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

Más vale tarde que nunca, déjame actualizar la respuesta de Nik del lado de la corrección. Mi solución es más lenta, pero funciona con cualquier número de archivos, con cualquier símbolo en los nombres de archivo, y puede ejecutarlo con sudo normalmente (pero tenga cuidado de que pueda descubrir diferentes archivos con sudo).

Peter K
fuente
Esta es una degradación de la respuesta de Nik . ¿Por qué crees que hay algo malo con la respuesta de Nik?
Scott
@Scott, la respuesta de Nik falla con (muy) gran cantidad de archivos.
Peter K
Estoy 99% seguro de que te equivocas. ¿Puede proporcionar alguna evidencia para respaldar su reclamo?
Scott
Sí, parece que estoy equivocado de hecho. find ... + parece romper la línea en múltiples comandos, ¡buena captura!
Peter K
0

Prueba este script de Python; no requiere generación de procesos y solo hace dos syscalls por archivo. Además de una implementación en C, probablemente será la forma más rápida de hacerlo (lo necesitaba para arreglar un sistema de archivos de 15 millones de archivos que estaban configurados en 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)

En mi caso, se requirió un try / catch alrededor del último chmod, ya que chmodding algunos archivos especiales fallaron.

ratones
fuente
-1

También puedes usar tree:

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

y si quieres ver también la carpeta agrega un eco

 tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 "$1" && echo$1' -- '{}'
Eduard Florinescu
fuente
@Scott 1) ​​Tienes razón sobre + x cambié a 755; 2) 3) para resolver esto puse el marcador de posición en una comilla simple como esta '{}'
Eduard Florinescu
@Scott Estoy de acuerdo en que esta no es la mejor respuesta, también es lenta, pero se irá de aquí para fines "didácticos" xargs. Las comillas simples en los nombres de archivo son en sí mismas un problema para muchos comandos y guiones, por eso enumeré todos los archivos que contienen comillas simples y los
eliminé
@Scott En mis sistemas busqué todos los archivos que contenían comillas simples y reemplacé las comillas simples
Eduard Florinescu
@Scott ¿Cómo solucionaría el hecho de que xargs no resuelve correctamente las comillas simples?
Eduard Florinescu
Continuemos esta discusión en el chat .
Eduard Florinescu
-2

Puede usar el siguiente script bash como ejemplo. Asegúrese de darle permisos ejecutables (755). Simplemente use ./autochmod.sh para el directorio actual, o ./autochmod.sh <dir> para especificar uno 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
usuario26528
fuente
2
¡Guauu! ¡Tantos problemas! (1) Si $1no es nulo, pero no es el nombre de un directorio (p. Ej., Es un error tipográfico), dirse configura .sin mensaje. (2) $1debería ser "$1"y $dirdebería ser "$dir". (3) No necesitas decirlo "./"; "."está bien (y, estrictamente hablando, no necesita citas aquí). (4) Esta no es una solución recursiva. (5) En mi sistema, ls -l … | awk '{ print $8 }'obtiene los tiempos de modificación de los archivos. Necesita { print $9 }obtener la primera palabra del nombre del archivo. E incluso entonces, (6) esto no maneja nombres de archivos con espacios en blanco. ...
Scott
1
... Y, por último pero no menos importante (∞) si este script se encuentra en el directorio actual, lo hará chmod a 644, con lo que en sí no ejecutable!
Scott