545

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

И наоборот, как chmod только файлы (рекурсивно), но без каталога?

8 ответов8

764

Чтобы рекурсивно дать каталогам права на чтение и выполнение:

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
276

Распространенной причиной такого рода вещей является установка каталогов на 755, а файлов на 644. В этом случае есть немного более быстрый способ, чем пример find Ника:

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

Имея в виду:

  • -R = рекурсивно;
  • u+rwX = Пользователи могут читать, писать и выполнять;
  • go+rX = group и другие могут читать и выполнять;
  • go-w = группа и другие не могут писать

Здесь важно отметить, что прописные буквы X действуют иначе, чем строчные буквы x . В руководстве мы можем прочитать:

Биты выполнения / поиска, если файл является каталогом, или любой из битов выполнения / поиска установлены в исходном (неизмененном) режиме.

Другими словами, chmod u+X в файле не устанавливает бит выполнения; и g+X установит его, только если он уже установлен для пользователя.

13

Если вы хотите убедиться, что для файлов установлено значение 644, и в пути есть файлы с флагом выполнения, вам сначала нужно будет удалить флаг выполнения. +X не удаляет флаг выполнения из файлов, у которых он уже есть.

Пример:

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

Обновление: кажется, что это не сработало, потому что первое изменение (ugo-x) делает каталог неисполнимым, поэтому все файлы под ним не изменяются.

4

Я решил написать небольшой сценарий для этого сам.

Рекурсивный скрипт chmod для директорий и / или файлов - Gist

Он в основном делает рекурсивный chmod, но также обеспечивает некоторую гибкость для параметров командной строки (устанавливает права доступа к каталогу и / или файлу или исключает оба, он автоматически сбрасывает все до 755-644). Он также проверяет несколько сценариев ошибок.

Я также написал об этом в своем блоге.

2

Чтобы рекурсивно дать каталогам права на чтение и выполнение:

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

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

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

Лучше поздно, чем никогда, позвольте мне обновить ответ Ника на стороне правильности. Мое решение медленнее, но оно работает с любым количеством файлов, с любыми символами в именах файлов, и вы можете запустить его с помощью sudo в обычном режиме (но помните, что он может обнаружить другие файлы с помощью sudo).

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' -- '{}'
-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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .