Як рекурсивно chmod всі каталоги, крім файлів?


573

Як chmod 755 всі каталоги, але не файл (рекурсивно)?

І навпаки, як chmod тільки файли (рекурсивно), але немає каталогу?



Відповіді:


801

Щоб рекурсивно надавати каталогів читання та виконання привілеїв:

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

Щоб рекурсивно надавати файлам права читання:

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

Або, якщо є багато об'єктів для обробки:

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

Або для зменшення chmodнересту:

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
Перші два приклади обов'язково для каталогів з дуже великою кількістю файлів: -bash: /bin/chmod: Argument list too long. Остання команда працює з багатьма файлами, але при використанні sudoпотрібно бути обережним, щоб поставити її перед xargs замість chmod:find /path/to/base/dir -type d -print0 | sudo xargs -0 chmod 755
Agargara

2
Також до відома, ці команди з урахуванням базової директорії. Отже, у наведеному вище прикладі dirтакож буде встановлено 755.
CenterOrbit

2
chmod ... $(find /path/to/base/dir -type ...)не вдається встановити назви файлів з пробілами в назві.
Дан Даскалеску

7
Я вважаю, що найправильніша (але не найшвидша) версія щодо пробілів та символів у назви файлів та кількості файлів find /path/to/base/dir -type d -exec chmod 755 {} \;( find /path/to/base/dir -type f -exec chmod 644 {} \;).
Пітер К

Зауважте, що це стосується лише першого шару, який він може прочитати. Вам доведеться виконати його кілька разів, щоб заглибитися в дерево каталогів.
Хенк Полі

290

Поширеною причиною такого роду речей є встановлення каталогів на 755, а файлів на 644. У цьому випадку є трохи швидший спосіб, ніж findприклад nik :

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

Значення:

  • -R = рекурсивно;
  • u+rwX = Користувачі можуть читати, писати та виконувати;
  • go+rX = група та інші можуть читати та виконувати;
  • go-w = група та інші не можуть писати

Тут важливо зазначити, що великі Xрегістри по-різному діють на малі x. У посібнику ми можемо прочитати:

Біти виконання / пошуку, якщо файл - це каталог, або будь-який із бітів виконання / пошуку встановлений у вихідному (немодифікованому) режимі.

Іншими словами, chmod u + X у файлі не встановить біт виконання; і g + X встановить його лише тоді, коли він уже встановлений для користувача.


5
-R = рекурсивно; u + rwX = Користувачі можуть читати, писати та виконувати; go + rX = група та інші можуть читати та виконувати; go-w = група та інші не можуть писати
säcker

23
Ця схема не виправить ситуацію, коли хтось зробив, chmod -R 777оскільки +Xопція не скидає існуючі біти виконання файлів. Використання -x скидає каталоги та запобігає спуску в них.
Ендрю Віт

3
@ ring0: Я не збираюся відповідати на питання буквально як поставлене - nik це вже зробив чудово. Я вказую на більш дешеве рішення для найпоширенішого випадку. І так, ви отримуєте різні дозволи для файлів і каталогів X, як пояснено в коментарях.
bobince

6
go+rX,go-w-> go=rXчи не так?
П’єр де ЛЕСПІНАЙ

5
Ви також можете використовувати chmod u-x,u+Xв комбінації тощо, щоб видалити виконавчі біти для файлів, але додати їх до каталогів.
w0rp

14

Якщо ви хочете переконатися, що для файлів встановлено 644, а на шляху, який містить прапор виконання, є файли, спочатку потрібно буде видалити прапор виконання. + X не видаляє прапор виконання з файлів, які вже мають його.

Приклад:

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

Оновлення: це, здається, не вдається, оскільки перша зміна (ugo-x) робить каталог невиконаним, тому всі файли під ним не змінюються.


1
Це працює для мене, і я не бачу, чому б цього не сталося. (Звичайно, якщо ви просто зробили це chmod -R ugo-x path, це може бути проблемою. Але повна команда виконає команду у chmod u+rwXкожному каталозі, перш ніж вона спробує спуститися в неї.) Однак я вважаю, що chmod R u=rw,go=r,a+X pathцього достатньо - і це коротше.
Скотт

Я виявив, що це справно працює; не було проблем із введенням каталогів
Хтось Десь

4

Я вирішив написати для цього невеликий сценарій.

Рекурсивний сценарій chmod для dirs та / або файлів - 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

В основному це робить рекурсивний chmod, але також надає трохи гнучкості для параметрів командного рядка (встановлює дозволи для каталогу та / або файлів або виключає обидва, він автоматично скидає все до 755-644). Він також перевіряє наявність декількох сценаріїв помилок.

Я також писав про це у своєму блозі .


2

Щоб рекурсивно надавати каталогів читання та виконання привілеїв:

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

Щоб рекурсивно надавати файлам права читання:

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

Краще пізно, ніж ніколи, дозвольте мені доповнити відповідь nik з боку коректності. Моє рішення більш повільне, але воно працює з будь-якою кількістю файлів, з будь-якими символами в іменах файлів, і ви можете запускати його з sudo нормально (але будьте уважні, що він може виявити різні файли за допомогою sudo).


Це пониження відповіді nik . Чому ти вважаєш, що у відповіді nik щось не так?
Скотт

@Scott, відповідь nik не відповідає (vey) великій кількості файлів.
Петро К

Я на 99% впевнений, що ви помиляєтесь. Чи можете ви надати якісь докази на підтвердження вашої вимоги?
Скотт

Так, схоже, я дійсно помиляюся. знайди ... + начебто розбиває рядок на кілька команд, приємний улов!
Пітер К

0

Спробуйте цей сценарій python; він не вимагає нерестування процесів і робить лише два систематичні виклики на файл. Крім реалізації в C, це, мабуть, буде найшвидшим способом зробити це (мені знадобилося, щоб виправити файлову систему з 15 мільйонів файлів, які були встановлені на 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)

У моєму випадку для останнього chmod було потрібно спробувати / улов, оскільки chmodding деякі спеціальні файли не вдалося.


-1

Ви також можете використовувати tree:

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

і якщо ви хочете також переглянути папку, додайте відлуння

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

@Scott 1) ​​Ви маєте рацію приблизно + x я змінив 755; 2) 3) щоб вирішити це питання, я помістив заповнювач в одну цитату, як-от "{}"
Едуард Флоринеску

@Scott Я погоджуюсь, що це не найкраща відповідь і повільна, але залиште тут для "дидактичних" цілей також коментарі пояснять далі, також люди можуть дізнатися про xargsпроблеми. Одиночні цитати у іменах самі по собі є проблемою для багатьох команд та сценаріїв, тому я перерахував усі файли, що містять одиничні лапки, і видалив їх (цитати, які я маю на увазі)
Едуард Флорінеску

@Scott У моїх системах я шукав усі файли, які містили одинарні лапки і замінив єдині лапки
Eduard Florinescu

@Scott Як би ви виправили той факт, що xargs не вирішує правильно єдині лапки?
Едуард Флорінеску


-2

Ви можете використовувати наступний скрипт bash як приклад. Обов’язково надайте йому виконавчі дозволи (755). Просто використовуйте ./autochmod.sh для поточного каталогу або ./autochmod.sh <dir>, щоб вказати інший.

#!/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
Оце Так! Стільки проблем! (1) Якщо $1не є нульовим, але це не ім'я каталогу (наприклад, це помилка друку), то dirвстановлюється значення .без повідомлення. (2) $1має бути "$1"і $dirмає бути "$dir". (3) Вам не потрібно говорити "./"; "."це добре (і, строго кажучи, тут вам не потрібні цитати). (4) Це не рекурсивне рішення. (5) У моїй системі ls -l … | awk '{ print $8 }'отримує час модифікації файлів. Потрібно { print $9 }отримати перше слово імені файлу. І навіть тоді (6) це не обробляє назви файлів з пробілом. …
Скотт

1
... І останнє , але не менш (∞) , якщо цей сценарій знаходиться в поточному каталозі, він буде chmod сам до 644, тим самим роблячи себе не виконує!
Скотт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.