Jak rekurencyjnie chmod wszystkie katalogi oprócz plików?

Odpowiedzi:

801

Aby rekurencyjnie nadać katalogom uprawnienia do odczytu i wykonywania:

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

Aby rekurencyjnie nadać plikom uprawnienia do odczytu:

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

Lub, jeśli istnieje wiele obiektów do przetworzenia:

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

Lub, aby ograniczyć chmododradzanie:

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
źródło
7
Pierwsze dwa przykłady nie dla katalogów ze zbyt wielu plików: -bash: /bin/chmod: Argument list too long. Ostatnie polecenie działa z wieloma plikami, ale podczas korzystania z sudonich należy uważać, aby umieścić je przed xargs zamiast chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara,
2
Należy również zauważyć, że polecenia te obejmują katalog podstawowy. Tak więc w powyższym przykładzie dirzostanie również ustawiona wartość 755.
CenterOrbit
2
chmod ... $(find /path/to/base/dir -type ...)kończy się niepowodzeniem dla nazw plików ze spacjami w nazwie.
Dan Dascalescu
7
Myślę, że najbardziej poprawną (ale nie najszybszą) wersją pod względem spacji i symboli w nazwach plików i liczbie plików jest find /path/to/base/dir -type d -exec chmod 755 {} \;( find /path/to/base/dir -type f -exec chmod 644 {} \;).
Peter K
Pamiętaj, że dotyczy to tylko pierwszej warstwy, którą może odczytać. Będziesz musiał wykonać go kilka razy, aby wejść głębiej w drzewo katalogów.
Henk Poley
290

Typowym powodem tego rodzaju rzeczy jest ustawienie katalogów na 755, a plików na 644. W tym przypadku jest nieco szybszy sposób niż w findprzykładzie Nik :

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

Znaczenie:

  • -R = rekurencyjnie;
  • u+rwX = Użytkownicy mogą czytać, pisać i wykonywać;
  • go+rX = grupa i inni mogą czytać i wykonywać;
  • go-w = grupa i inni nie mogą pisać

Należy tutaj zauważyć, że wielkie litery Xdziałają inaczej niż małe litery x. W instrukcji możemy przeczytać:

Bity wykonania / wyszukiwania, jeśli plik jest katalogiem lub którykolwiek z bitów wykonania / wyszukiwania jest ustawiony w oryginalnym (niezmodyfikowanym) trybie.

Innymi słowy, chmod u + X na pliku nie ustawi bitu wykonania; a g + X ustawi to tylko, jeśli jest już ustawione dla użytkownika.

Bobin
źródło
5
-R = rekurencyjnie; u + rwX = Użytkownicy mogą czytać, pisać i wykonywać; go + rX = grupa i inni mogą czytać i wykonywać; go-w = grupa i inni nie mogą pisać
släcker
23
Ten wzorzec nie naprawi sytuacji, gdy ktoś to zrobił, chmod -R 777ponieważ +Xopcja nie zresetuje istniejących bitów wykonania plików. Użycie -x spowoduje zresetowanie katalogów i zapobiegnie zejściu do nich.
Andrew Vit,
3
@ ring0: Nie zamierzam odpowiadać na pytanie dosłownie, jak postawiono - nik zrobił to już doskonale. Wskazuję tańsze rozwiązanie najczęstszego przypadku. I tak, masz różne uprawnienia do plików i katalogów X, jak wyjaśniono w komentarzach.
bobince
6
go+rX,go-w-> go=rXprawda?
Pierre de LESPINAY
5
Możesz także użyć chmod u-x,u+Xw kombinacji itp., Aby usunąć bity wykonania dla plików, ale dodać je do katalogów.
w0rp 4.04.16
14

Jeśli chcesz się upewnić, że pliki są ustawione na 644 i na ścieżce znajdują się pliki z flagą wykonania, najpierw musisz usunąć flagę wykonania. + X nie usuwa flagi wykonania z plików, które już ją mają.

Przykład:

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

Aktualizacja: wydaje się, że kończy się to niepowodzeniem, ponieważ pierwsza zmiana (ugo-x) powoduje, że katalog jest niewykonalny, więc wszystkie pliki pod nim nie są zmieniane.

mpolden
źródło
1
To działa dla mnie i nie rozumiem, dlaczego tak się nie stanie. (Jasne, jeśli właśnie to zrobiłeś chmod -R ugo-x path, może to być problem. Ale pełne polecenie wykona chmod u+rwXkażdy katalog przed próbą zejścia do niego.) Uważam jednak, że chmod R u=rw,go=r,a+X pathto wystarczy - i jest krótsze.
Scott
Odkryłem, że działało to poprawnie; nie było problemów z wejściem do katalogów
Someone Somewhere
4

Postanowiłem napisać do tego mały skrypt.

Rekurencyjny skrypt chmod dla katalogów i / lub plików - 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

Zasadniczo robi rekurencyjny chmod, ale zapewnia także trochę elastyczności opcjom wiersza poleceń (ustawia uprawnienia do katalogu i / lub plików lub wyklucza oba, automatycznie resetuje wszystko do 755-644). Sprawdza także kilka scenariuszy błędów.

Pisałem również o tym na moim blogu .

francisbyrne
źródło
2

Aby rekurencyjnie nadać katalogom uprawnienia do odczytu i wykonywania:

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

Aby rekurencyjnie nadać plikom uprawnienia do odczytu:

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

Lepiej późno niż nigdy nie pozwól mi zaktualizować odpowiedzi Nik po stronie poprawności. Moje rozwiązanie jest wolniejsze, ale działa z dowolną liczbą plików, z dowolnymi symbolami w nazwach plików, i możesz normalnie uruchamiać go z sudo (ale uważaj, że sudo może odkryć różne pliki).

Peter K.
źródło
To jest obniżenie poziomu odpowiedzi Nik . Dlaczego wierzysz, że coś jest nie tak z odpowiedzią Nik?
Scott,
@Scott, odpowiedź nika kończy się niepowodzeniem przy (vey) dużej liczbie plików.
Peter K,
Jestem w 99% pewien, że się mylisz. Czy możesz przedstawić dowody na poparcie swojego roszczenia?
Scott,
Tak, wygląda na to, że naprawdę się mylę. znajdź ... + wydaje się, że dzieli linię na wiele poleceń, niezły chwyt!
Peter K
0

Wypróbuj ten skrypt Pythona; nie wymaga odradzania procesów i wykonuje tylko dwa wywołania systemowe na plik. Oprócz implementacji w C, będzie to prawdopodobnie najszybszy sposób na zrobienie tego (potrzebowałem go, aby naprawić system plików zawierający 15 milionów plików, które zostały ustawione na 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)

W moim przypadku wymagana była próba / catch wokół ostatniego chmod, ponieważ chmodding niektórych plików specjalnych nie powiodło się.

mic_e
źródło
-1

Możesz także użyć tree:

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

a jeśli chcesz również wyświetlić folder, dodaj echo

 tree -faid /your_directory | xargs -L1 -I{} bash -c 'sudo chmod 755 "$1" && echo$1' -- '{}'
Eduard Florinescu
źródło
@ Scott 1) ​​Masz rację co do + x Zmieniłem na 755; 2) 3) Aby rozwiązać ten problem, umieściłem symbol zastępczy w jednym cudzysłowie, takim jak ten „{}”
Eduard Florinescu,
@Scott Zgadzam się, że nie jest to najlepsza odpowiedź również jest powolna, ale zostawiam ją tutaj w celach „dydaktycznych” również komentarze wyjaśnią dalej, również ludzie mogą dowiedzieć się o xargsproblemach. Pojedyncze cytaty w nazwach plików same w sobie stanowią problem dla wielu poleceń i skryptów, dlatego wymieniłem wszystkie pliki zawierające pojedyncze cytaty i usunąłem je (mam na myśli cytaty)
Eduard Florinescu,
@ Scott W moich systemach szukałem wszystkich plików, które zawierały pojedyncze cytaty i zamieniłem pojedyncze cytaty
Eduard Florinescu,
@ Scott Jak naprawiłbyś fakt, że xargs nie rozwiązuje poprawnie pojedynczych cudzysłowów?
Eduard Florinescu,
Daj nam kontynuować tę dyskusję w czacie .
Eduard Florinescu,
-2

Możesz użyć następującego skryptu bash jako przykładu. Pamiętaj, aby nadać mu uprawnienia do wykonywania (755). Wystarczy użyć ./autochmod.sh dla bieżącego katalogu lub ./autochmod.sh <katalog>, aby określić inny katalog.

#!/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
użytkownik26528
źródło
2
Łał! Tyle problemów! (1) Jeśli $1nie ma wartości null, ale nie jest nazwą katalogu (np. Literówka), dirzostaje ustawiony na .brak wiadomości. (2) $1powinno być "$1"i $dirpowinno być "$dir". (3) Nie musisz mówić "./"; "."jest w porządku (i ściśle mówiąc, nie potrzebujesz tutaj cytatów). (4) To nie jest rozwiązanie rekurencyjne. (5) W moim systemie ls -l … | awk '{ print $8 }'pobiera czasy modyfikacji plików. Musisz { print $9 }uzyskać pierwsze słowo nazwy pliku. I nawet wtedy (6) nie obsługuje nazw plików z białą spacją. …
Scott
1
… I wreszcie (∞), jeśli ten skrypt znajduje się w bieżącym katalogu, chmod sam przejdzie na 644, przez co sam się nie wykona !
Scott