相反,如何chmod 755所有目录但不包含文件(递归)?

相反,如何仅对文件进行chmod(递归)而不包含目录?

评论

相关:在SO
上将目录的所有文件和文件夹权限更改为644/755
相关:在U&L处使用一个命令更改所有文件夹权限。

#1 楼

递归地授予目录读取和执行特权:

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


评论


前两个示例对于文件过多的目录失败:-bash:/ bin / chmod:参数列表过长。最后一个命令可用于许多文件,但是在使用sudo时,必须小心将其放在xargs之前而不是chmod上:find / path / to / base / dir -type d -print0 |苏多xargs -0 chmod 755

– Agargara
17年11月7日在1:06



还要注意,这些命令包含基本目录。因此,在上面的示例中,dir也将设置为755。

–CenterOrbit
18年1月16日,0:16

chmod ... $(查找/ path / to / base / dir -type ...)对于名称中带有空格的文件名失败。

– Dan Dascalescu
18年2月6日,下午1:58

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

– Peter K
18年2月21日在11:49

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

–汉克·波利(Henk Poley)
19年4月14日在18:56

#2 楼

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

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


含义:



-R =递归;

u+rwX =用户可以读取,写入和执行;

go+rX =组并且其他人可以读取和执行;

go-w =组而其他人则不能编写

这里要注意的重要一点是,大写X的行为与小写x不同。在手册中,我们可以阅读:


如果文件是目录,或者任何执行/搜索位设置为原始(未修改)模式,则执行/搜索位。

评论


-R =递归; u + rwX =用户可以读取,写入和执行; go + rX = group,其他人可以读取和执行; go-w =小组,其他人不能写

–släcker
2010年1月6日7:08



当有人完成chmod -R 777时,此模式无法解决这种情况,因为+ X选项不会重置文件上现有的执行位。使用-x将重置目录,并阻止其进入目录。

–安德鲁·维特(Andrew Vit)
2012年8月7日在4:57

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

– bobince
2012年10月28日在1:05

go + rX,go-w-> go = rX是吗?

– Pierre de LESPINAY
2014-09-22 14:24



您还可以结合使用chmod u-x,u + X等来删除文件的执行位,但将其添加到目录中。

– w0rp
16年4月4日在18:27

#3 楼

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

示例:

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


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

评论


这对我有用,我不明白为什么不这样做。 (当然,如果您只是执行chmod -R ugo-x路径,则可能会出现问题。但是在尝试进入每个目录之前,complete命令将在每个目录上执行chmod u + rwX。)但是,我相信chmod R u = rw,go = r,a + X路径就足够了-而且更短。

–斯科特
2014年7月8日,0:25

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

–有人支持Monica
18年6月16日在12:54

整洁,这很好用-

– Jesse C
4月8日23:43

#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: q4312078q 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  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=

# 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。它还会检查一些错误情况。

我也在我的博客上写过它。

评论


有没有办法防止文件夹。从获得许可更改?

– MaXi32
6月23日0:50

#5 楼

递归授予目录读取和执行特权:

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的答案有什么问题?

–斯科特
18-10-9在23:06

@ Scott,nik的答案失败,其中包含(非常)大量的文件。

– Peter K
18-10-25在14:54

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

–斯科特
18-10-25在23:56

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

– Peter K
18-10-28在13:40

#6 楼

试试这个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)


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

#7 楼

我发布解决方案是因为我看不到仅使用chmod的几乎所有情况的解决方案:
仅chmod:对文件和目录的平滑权限
对于我的示例,我创建了多个具有不同权限的文件:
> tree -p chmodtests/
chmodtests/
├── [drwxr-xr-x]  aa/
│   ├── [drwxr-xr-x]  a1/
│   │   ├── [-r--r--r--]  read_only
│   │   ├── [-rw-rw-rw-]  read_w
│   │   └── [-rwxrwxrwx]  read_wx*
│   ├── [drwxr-xr-x]  a2/
│   ├── [-r--------]  read_only
│   ├── [-rw-------]  read_w
│   └── [-rwx------]  read_wx*
└── [drwxr-xr-x]  bb/

4 directories, 6 files

然后应用以下命令:
 chmod -vR a=r-wx,u=wr,a+X chmodtests/
 

输出:
mode of 'chmodtests/' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa/a1' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa/a1/read_only' changed from 0444 (r--r--r--) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/a1/read_w' changed from 0666 (rw-rw-rw-) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/a1/read_wx' changed from 0777 (rwxrwxrwx) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/read_only' changed from 0400 (r--------) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/a2' retained as 0755 (rwxr-xr-x)
mode of 'chmodtests/aa/read_w' changed from 0600 (rw-------) to 0644 (rw-r--r--)
mode of 'chmodtests/aa/read_wx' changed from 0700 (rwx------) to 0644 (rw-r--r--)
mode of 'chmodtests/bb' retained as 0755 (rwxr-xr-x)

结果:所有文件均为644;所有Dirs均为755
> tree -p chmodtests/
chmodtests/
├── [drwxr-xr-x]  aa/
│   ├── [drwxr-xr-x]  a1/
│   │   ├── [-rw-r--r--]  read_only
│   │   ├── [-rw-r--r--]  read_w
│   │   └── [-rw-r--r--]  read_wx
│   ├── [drwxr-xr-x]  a2/
│   ├── [-rw-r--r--]  read_only
│   ├── [-rw-r--r--]  read_w
│   └── [-rw-r--r--]  read_wx
└── [drwxr-xr-x]  bb/

说明部分
tl; dr说明:
此命令删除对文件和目录的所有执行/搜索,然后仅对dirs添加执行/搜索
chmod -vR:冗长且递归
a=r-wx


a:表示所有(用户,组和其他)

=:将权限设置为(请勿添加或删除)

r-wx:只读权限

u=wr:用户可以读写
a+X:仅添加执行/搜索目录(适用于所有类型u,g,o)
其他示例
现在假设我只希望文件600和目录dirs:
chmod -vR a=-rwx,u=rw,u+X chmodtests/
限制
使用这种方法,您不能分别为文件和目录设置r和w。
例如您不能拥有以下内容
drwxr-xr-x dir/
-r-------- dir/myfile

hth

#8 楼

您还可以使用tree

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


,如果还要查看文件夹,请添加回显

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


评论


@Scott 1)你对+ x是正确的,我改为755; 2)3)为了解决这个问题,我将占位符放在单引号中,例如“ {}”

–爱德华(Eduard Florinescu)
18-10-10在5:53

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

–爱德华(Eduard Florinescu)
18-10-10在6:16



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

–爱德华(Eduard Florinescu)
18-10-10在6:42



@Scott您将如何解决xargs不能正确解决单引号的问题?

–爱德华(Eduard Florinescu)
18-10-10在7:20

让我们继续聊天中的讨论。

–爱德华(Eduard Florinescu)
18-10-10在7:26

#9 楼

您可以使用以下bash脚本作为示例。确保为其授予可执行权限(755)。只需将./autochmod.sh用于当前目录,或将./autochmod.sh 用于指定其他目录。

#!/bin/bash

if [ -e  ]; then
    if [ -d  ];then
        dir=
    else
        echo "No such directory: "
        exit
    fi
else
    dir="./"
fi

for f in $(ls -l $dir | awk '{print }'); do
    if [ -d $f ];then
        chmod 755 $f
    else
        chmod 644 $f
    fi
done


评论


哇!这么多问题! (1)如果$ 1不为null,但不是目录名称(例如,是错字),则dir设置为。没有消息。 (2)$ 1应该是“ $ 1”,$ dir应该是“ $ dir”。 (3)您无需说“ ./”; “。”很好(严格来说,您在这里不需要引号)。 (4)这不是递归解决方案。 (5)在我的系统上,ls -l…| awk'{print $ 8}'获取文件的修改时间。您需要{print $ 9}来获取文件名的第一个单词。即使这样,(6)仍不能处理带有空格的文件名。 …

–斯科特
2014年7月7日在22:59



…而且,最后但并非最不重要的(∞),如果此脚本位于当前目录中,它将chmod自身更改为644,从而使其自身不可执行!

–斯科特
2014年7月7日23:00