Come ricodificare ricorsivamente tutte le directory tranne i file?


Risposte:


802

Per assegnare in modo ricorsivo alle directory i privilegi di lettura ed esecuzione:

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

Per assegnare in modo ricorsivo i privilegi di lettura dei file :

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

Oppure, se ci sono molti oggetti da elaborare:

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

Oppure, per ridurre la chmoddeposizione delle uova:

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
I primi due esempi falliscono per directory con troppi file: -bash: /bin/chmod: Argument list too long. L'ultimo comando funziona con molti file, ma quando ne usi sudouno devi fare attenzione a metterlo prima di xargs invece di chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara,

2
Inoltre, questi comandi sono comprensivi della dir di base. Quindi, nell'esempio sopra, dirverrà impostato anche su 755.
CenterOrbit

2
chmod ... $(find /path/to/base/dir -type ...)non riesce per i nomi di file con spazi nel nome.
Dan Dascalescu,

7
Penso che la versione più corretta (ma non più veloce) rispetto agli spazi e ai simboli nei nomi dei file e nel numero di file sia find /path/to/base/dir -type d -exec chmod 755 {} \;( find /path/to/base/dir -type f -exec chmod 644 {} \;).
Peter K,

Nota che questo vale solo per il primo livello che può leggere. Dovrai eseguirlo più volte per approfondire la struttura delle directory.
Henk Poley,

290

Un motivo comune per questo genere di cose è impostare le directory su 755 ma i file su 644. In questo caso c'è un modo leggermente più veloce finddell'esempio di Nik :

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

Senso:

  • -R = ricorsivamente;
  • u+rwX = Gli utenti possono leggere, scrivere ed eseguire;
  • go+rX = gruppo e altri possono leggere ed eseguire;
  • go-w = gruppo e altri non possono scrivere

La cosa importante da notare qui è che le maiuscole Xagiscono diversamente dalle lettere minuscole x. Nel manuale possiamo leggere:

I bit di esecuzione / ricerca se il file è una directory o uno dei bit di esecuzione / ricerca sono impostati nella modalità originale (non modificata).

In altre parole, chmod u + X su un file non imposterà il bit di esecuzione; e g + X lo imposteranno solo se è già impostato per l'utente.


5
-R = ricorsivamente; u + rwX = Gli utenti possono leggere, scrivere ed eseguire; go + rX = group e altri possono leggere ed eseguire; go-w = group e altri non sanno scrivere
släcker

23
Questo modello non risolverà la situazione quando qualcuno lo ha fatto chmod -R 777poiché l' +Xopzione non ripristinerà i bit di esecuzione esistenti sui file. L'uso di -x reimposta le directory e impedisce di scendere in esse.
Andrew Vit,

3
@ ring0: non ho intenzione di rispondere alla domanda letteralmente come posato - Nik ha già fatto perfettamente. Sto indicando una soluzione più economica per il caso più comune. E sì, ottieni autorizzazioni diverse per file e directory con X, come spiegato nei commenti.
bobince,

6
go+rX,go-w-> go=rXnon è vero?
Pierre de LESPINAY,

5
È inoltre possibile utilizzare chmod u-x,u+Xin combinazione, ecc., Per rimuovere i bit di esecuzione per i file, ma aggiungerli per le directory.
w0rp,

14

Se vuoi assicurarti che i file siano impostati su 644 e ci siano file nel percorso che hanno il flag di esecuzione, dovrai prima rimuovere il flag di esecuzione. + X non rimuove il flag di esecuzione dai file che già lo hanno.

Esempio:

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

Aggiornamento: questo sembra non riuscire perché la prima modifica (ugo-x) rende la directory non eseguibile, quindi tutti i file sottostanti non vengono modificati.


1
Questo funziona per me e non vedo perché non dovrebbe. (Certo, se lo facessi chmod -R ugo-x path, potrebbe essere un problema. Ma il comando completo eseguirà l'operazione chmod u+rwXsu ciascuna directory prima che tenti di discenderla.) Tuttavia, credo che chmod R u=rw,go=r,a+X pathsia sufficiente - ed è più breve.
Scott,

Ho trovato che ha funzionato correttamente; non ci sono stati problemi con l'accesso alle directory
Someone Somewhere,

4

Ho deciso di scrivere una piccola sceneggiatura per questo.

Script ricorsivo chmod per dirs e / o file - 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

Fondamentalmente fa il chmod ricorsivo, ma offre anche un po 'di flessibilità per le opzioni della riga di comando (imposta i permessi di directory e / o file, o esclude entrambi ripristina automaticamente tutto a 755-644). Verifica inoltre alcuni scenari di errore.

Ne ho anche scritto sul mio blog .


2

Per assegnare in modo ricorsivo alle directory i privilegi di lettura ed esecuzione:

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

Per assegnare in modo ricorsivo i privilegi di lettura dei file :

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

Meglio tardi che mai, lasciami aggiornare la risposta di Nik dal lato della correttezza. La mia soluzione è più lenta, ma funziona con qualsiasi numero di file, con qualsiasi simbolo nei nomi dei file e puoi eseguirla normalmente con sudo (ma attenzione che potrebbe scoprire file diversi con sudo).


Questo è un downgrade della risposta di Nik . Perché credi che ci sia qualcosa di sbagliato nella risposta di Nik?
Scott,

@Scott, la risposta di Nik non riesce con (vey) un gran numero di file.
Peter K,

Sono sicuro al 99% che ti sbagli. Potete fornire prove a sostegno del vostro reclamo?
Scott,

Sì, sembra che mi sbagli davvero. trova ... + sembra spezzare la linea in più comandi, bella cattura!
Peter K,

0

Prova questo script Python; non richiede la generazione di processi e fa solo due syscalls per file. A parte un'implementazione in C, sarà probabilmente il modo più veloce per farlo (ne avevo bisogno per riparare un filesystem di 15 milioni di file che erano tutti impostati su 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)

Nel mio caso, era necessario un tentativo / cattura attorno all'ultimo chmod, poiché alcuni file speciali non erano riusciti.


-1

Puoi anche usare tree:

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

e se vuoi vedere anche la cartella aggiungi un'eco

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

@Scott 1) ​​Hai ragione circa + x Ho cambiato in 755; 2) 3) per risolvere questo ho messo il segnaposto in una virgoletta come questa '{}'
Eduard Florinescu,

@Scott Sono d'accordo che questa non è la risposta migliore è anche lenta, ma partirà qui per scopi "didattici" anche i commenti spiegheranno ulteriormente, anche le persone possono conoscere i xargsproblemi. Le virgolette singole nei nomi dei file sono esse stesse un problema per molti comandi e script, per questo motivo ho elencato tutti i file contenenti virgolette singole e li ho rimossi (le virgolette intendo)
Eduard Florinescu,

@Scott Sui miei sistemi ho cercato tutti i file che contenevano virgolette singole e ho sostituito le virgolette singole
Eduard Florinescu,

@Scott Come risolveresti il ​​fatto che xargs non risolva correttamente le virgolette singole?
Eduard Florinescu,


-2

È possibile utilizzare il seguente script bash come esempio. Assicurati di concedergli le autorizzazioni eseguibili (755). Basta usare ./autochmod.sh per la directory corrente o ./autochmod.sh <dir> per specificarne una diversa.

#!/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
Wow! Così tanti problemi! (1) Se $1non è null, ma non è il nome di una directory (ad esempio, è un refuso), dirviene impostato su .senza messaggio. (2) $1dovrebbe essere "$1"e $dirdovrebbe essere "$dir". (3) Non è necessario dirlo "./"; "."va bene (e, a rigor di termini, non hai bisogno di citazioni qui). (4) Questa non è una soluzione ricorsiva. (5) Sul mio sistema, ls -l … | awk '{ print $8 }'ottiene i tempi di modifica dei file. È necessario { print $9 }ottenere la prima parola del nome file. E anche allora, (6) questo non gestisce i nomi di file con spazi bianchi. ...
Scott,

1
… E, ultimo ma non meno importante (∞) se questo script si trova nella directory corrente, sarà esso chmod stesso a 644, rendendosi quindi non eseguibile!
Scott,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.