如何创建多个嵌套目录并在一个命令中定义所有目录的权限?

如何创建多个嵌套目录并在一个命令中定义所有目录的权限?

在 Linux 中,以下两个命令按预期工作:

mkdir -m 555 new_directory
mkdir -p a/b/c

但以下不起作用正如预期的那样

mkdir -m 555 -p a/b/c

已创建 3 个目录,但只有最新的目录获得555权限。和a目录b具有默认权限。

那么如何实现标题中描述的目标呢?是否可以?

顺便说一句 - 我选择了555一个随机案例,它666也失败777

答案1

如果您明确列出目录(父目录在前),则可以实现在一个命令中创建目录的既定目标:

mkdir -m 555 -p a a/b a/b/c

使用支持 csh 式大括号扩展的 shell,bash您可以稍微简化一下,但会牺牲可读性:

mkdir -m 555 -p a{,/b{,/c}}

但请注意,对于权限,555两个命令都会失败如果它确实需要创建任何父目录:此类目录是使用不允许写入的权限创建的,因此无法创建下一级目录。

最后,一个bashshell 脚本还可以通过将复杂性包装在一个函数中,为您提供根据请求在一个命令中创建多个目录的功能。这将尝试从下往上将权限应用于新创建的目录,因此最终可能会得到没有写入权限的目录:

mkdirs()
{
    local dirs=() modes=() dir old

    # Grab arguments
    [[ "$1" == '-m' ]] && modes=('-m' "$2") && shift 2
    dir=$1

    # Identify missing directories
    while [[ "$dir" != "$old" ]]
    do
        [[ ! -d "$dir" ]] && dirs+=("$dir")
        old="$dir"
        dir="${dir%/*}"
    done

    # Create necessary directories and maybe fix up permissions
    for dir in "${dirs[@]}"
    do
        mkdir -p "${modes[@]}" "$dir" || return 1
        [[ -n "${modes[1]}" ]] && chmod "${modes[1]}" "$dir"
    done
}

例子

mkdirs -m 555 a/b/c

ls -ld a a/b a/b/c
dr-xr-xr-x+ 1 roaima roaima 0 Jan  7 10:01 a
dr-xr-xr-x+ 1 roaima roaima 0 Jan  7 10:01 a/b
dr-xr-xr-x+ 1 roaima roaima 0 Jan  7 10:01 a/b/c

与往常一样,这个函数可以独立地放入可执行脚本中,该脚本位于您的以下位置$PATH

#!/bin/bash
mkdirs()
{
    ...as above...
}

mkdirs "$@"

答案2

它看起来确实mkdir没有应用-m创建中间目录时设置的模式。但是,至少在大多数情况下,您可以使用 来umask修改它为它们设置的权限。

作品umask清算权限位是在 umask 中,因此如果您希望中介具有例如权限0700,请将 umask 设置为0077。此处使用子 shell 来包含 umask 更改:

$ ( umask 0077; mkdir -p a/b )
$ ls -ld a
drwx------ 3 ilkkachu ilkkachu 4096 Jan  7 07:23 a/
$ ls -ld a/b
drwx------ 2 ilkkachu ilkkachu 4096 Jan  7 07:23 a/b/

同样,要获得权限0555,您可以将 umask 设置为0222。但这实际上对中介机构不起作用,它们是使用权限创建的0755。即增加所属用户的写权限。

POSIX 指定对于中间路径名组件的权限(参见选项下-p):

[...] mkdir 实用程序应创建 dir 的路径前缀的任何路径名组件,这些路径名组件不命名现有目录[相当于创建丢失的目录],然后使用chmod()以下参数调用该函数:[...]

 2. (S_IWUSR|S_IXUSR|~filemask)&0777作为模式参数的值,其中filemask是进程的文件模式创建掩码。

S_IWUSRS_IXUSR是这些权限位的 C 常量。)

GNU coreutils 在线手册说

-p--parents
为每个参数创建任何缺失的父目录,将其文件权限位设置为=rwx,u+wx,即使用 修改的 umask u+wx。忽略现有的父目录,并且不更改其文件权限位。

它接着说该-m选项不适用于这些,但因此您可以使用 umask 来控制它们的权限。

(虽然那里的文字看起来不太对劲,但它提到“umask 必须包含u=wx此方法才能工作”,这似乎缺少 umask 的反向含义。)


大概mkdir是这样做的,因为否则它将无法在没有写权限的情况下在刚刚创建的目录中创建下一个目录。x出于同样的原因,同样的情况也发生在访问/搜索 ( ) 权限位上。

因此,如果您想创建自己无法写入或搜索的目录,那么看起来您只能chmod在之后创建它们。否则,设置umask工作mkdir

答案3

您可以使用install以下命令(非标准命令,来自 80 年代的 BSD,也包含在 GNU coreutils 中):

install -m 555 -d a/b/c a/b a

或者使用支持csh-style 大括号扩展的 shell:

install -m 555 -d a{/b{/c,},}

请注意,如果目录组件事先已经存在,则它们的权限(它们指向符号链接的目录的权限)将是改变了到0555。

要仅更改新创建的目录组件的权限,您可以将其作为函数来执行。例如,在zsh

mkdirhierperm() {
  local mode=$1 dir=$2 dirs=()
  until [[ -d $dir ]] dirs[1,0]=$dir dir=$dir:h
  if (( $#dirs == 0 )); then
    (umask 77 && mkdir -p -- $dirs[-1]) &&
      chmod -- $mode $dirs
  fi
}

mkdirhierperm 555 a/b/c
mkdirhierperm 555 /full/path/to/some/new/dir

答案4

可以通过两步完成此操作:首先调用mkdir创建目录,然后运行find . -type d -exec chmod 555 {} \;以修改模式。

相关内容