如何递归chmod除文件外的所有目录?


Answers:


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 ...)名称中带有空格的文件名失败。
Dan Dascalescu

7
我认为关于文件名中的空格和符号以及文件数的最正确(但不是最快)的版本是find /path/to/base/dir -type d -exec chmod 755 {} \;find /path/to/base/dir -type f -exec chmod 644 {} \;)。
彼得·K

请注意,这仅到达它可以读取的第一层。您将不得不执行几次,以更深入地了解目录树。
Henk Poley

290

发生这种情况的常见原因是将目录设置为755,但将文件设置为644。在这种情况下,比nik的find示例要快一些:

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 = group,其他人可以读取和执行;去-W =组和其他人不能写
懒鬼

23
此模式无法解决某人完成的情况,chmod -R 777因为该+X选项不会重置文件上现有的执行位。使用-x将重置目录,并阻止其进入目录。
安德鲁·维特

3
@ ring0:我无意按字面意义回答问题-nik已经做得很好。我为最常见的情况指出了一种更便宜的解决方案。是的,您确实获得了对文件和目录的不同权限X,如注释中所述。
bobince 2012年

6
go+rX,go-w-> go=rX是吗?
Pierre de LESPINAY 2014年

5
您也可以chmod u-x,u+X组合使用等,以删除文件的执行位,但为目录添加它们。
w0rp

14

如果要确保将文件设置为644,并且路径中存在带有execute标志的文件,则必须先删除execute标志。+ X不会从已有的文件中删除执行标志。

例:

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

更新:这似乎失败了,因为第一个更改(ugo-x)使该目录不可执行,因此该目录下的所有文件均未更改。


1
这对我有用,我不明白为什么不这样做。(当然,如果只是chmod -R ugo-x path这样做了,那可能是个问题。但是complete命令将chmod u+rwX在尝试进入每个目录之前在每个目录上执行on。)但是,我认为这chmod R u=rw,go=r,a+X path已经足够了,而且它更短。
斯科特

我发现这工作正常;输入目录没有问题
某处某人

4

我决定为此写一个小脚本。

目录和/或文件的递归chmod脚本—要点

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的答案因传送大量文件而失败。
彼得·K

我有99%的把握确定您弄错了。您可以提供任何证据支持您的主张吗?
斯科特,

是的,看来我确实错了。find ... +似乎将行分成多个命令,不错!
彼得·K

0

试试这个python脚本;它不需要生成任何进程,并且每个文件仅执行两个syscall。除了用C实现之外,它可能是最快的方法(我需要它来修复包含1500万个文件的文件系统,这些文件都设置为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)

在我的情况下,由于chmodding一些特殊文件失败,因此需要在最后一个chmod周围进行try / catch。


-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)为了解决这个问题,我将占位符放在单引号中,例如'{}'
Eduard Florinescu 18-10-10,5

@斯科特我同意这不是最好的答案,但也很慢,但出于“指导性”目的将离开此处,评论将进一步解释,人们也可以了解xargs问题。文件名中的单引号本身就是许多命令和脚本的问题,这就是为什么我列出所有包含单引号的文件并将其删除(我的意思是引号)的原因
Eduard Florinescu 18-10-10,6

@Scott在我的系统上,我搜索了包含单引号的所有文件,并替换了单引号
Eduard Florinescu 18-10-10

@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不为null,但不是目录名(例如,是错字),则将其dir设置为.没有消息。(2)$1应该是"$1"并且$dir应该是"$dir"。(3)你不必说"./""."很好(严格来说,这里不需要引号)。(4)这不是递归解决方案。(5)在我的系统上,ls -l … | awk '{ print $8 }'获取文件的修改时间。您需要{ print $9 }获取文件名的第一个单词。即使这样,(6)仍不能处理带有空格的文件名。…
斯科特

1
…而且,最后但并非最不重要的(∞),如果此脚本位于当前目录中,它chmod 本身将变为644,从而使其自身不可执行!
斯科特(Scott)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.