1つのコマンドで複数のネストしたディレクトリを作成し、すべての権限を定義する方法は?

1つのコマンドで複数のネストしたディレクトリを作成し、すべての権限を定義する方法は?

Linuxでは、次の2つのコマンドが期待どおりに機能します。

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

ディレクトリを明示的に一覧表示すると(親ディレクトリが最初に)、1つのコマンドでディレクトリを作成するという指定された目標を達成できます。

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

cshスタイルの中かっこ拡張をサポートするシェルを使用すると、bash操作を少し簡素化できますが、読みやすさが低下します。

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

しかし、参考にしてください。特権の場合、555両方のコマンドは失敗します。親ディレクトリを作成する必要がある場合:これらのディレクトリは書き込みを許可しない権限で作成されるため、下位レベルのディレクトリを作成できません。

最後に、bashシェルスクリプトは複雑さを関数にラップして、単一のコマンドで要求に応じて複数のディレクトリを作成する機能を提供できます。これにより、新しく作成されたディレクトリに権限を下から上に適用しようとするため、書き込み権限のないディレクトリになる可能性があります。

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:弁済許可ビットは次のとおりです。置くたとえば、仲介者に権限を付与するには、umask0700をumaskに設定します0077。ここでは、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/

同様に、権限を得るために0555umaskを0222。ただし、これは実際に仲介者には機能せず、権限を使用して作成されます0755。つまり、所属するユーザーの書き込み権限を向上させます。

POSIXの指定中間パス名コンポーネントの権限(オプションの下を参照-p):

[...] mkdir ユーティリティは、既存のディレクトリに名前を指定しないdirのパスプレフィックスのパス名コンポーネントを生成し、[欠落ディレクトリの作成と同じ]次の引数を使用してchmod()関数を呼び出す必要があります。 [...]

 2. (S_IWUSR|S_IXUSR|~filemask)&0777モードパラメータの値で、filemaskプロセスのファイルモード生成マスクはどこにありますか?

S_IWUSRそしてS_IXUSRこれらの許可ビットのC定数です。)

これGNU coreutils オンラインマニュアルによると:

-p--parents
ファイル許可ビットをに設定して、各引数に対して欠落している親ディレクトリを作成します。=rwx,u+wxつまり、修正されたumaskを使用しますu+wx。既存の親ディレクトリは無視され、対応するファイル権限ビットは変更されません。

-mこのオプションはここには適用されませんが、umaskを使用してそのオプションの権限を制御できることを説明します。

(テキストが正しくないように見えますが、「umaskはu=wx機能するにはこのメソッドを含める必要があります」と言いますが、これはumaskの逆の意味がありません。)


おそらくmkdirこれを行う理由は、それ以外の場合は書き込み権限がないと、作成したディレクトリ内に次のディレクトリを作成できないためです。x同じ理由で、access/search() 許可ビットでも同じことが起こります。

したがって、書き込みまたは検索が不可能なディレクトリを作成したい場合は、chmod後でのみ作成できるように見えます。それ以外の場合は設定がumask機能しますmkdir

答え3

次のコマンドを使用できますinstall(80年代のBSDの非標準コマンド、GNU coreutilsにも含まれています):

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

またはcsh-style 中括弧拡張をサポートするシェルを使用します。

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

これは2つのステップで実行できます。まずmkdir、ディレクトリの作成を呼び出してから、実行してfind . -type d -exec chmod 555 {} \;スキーマを変更します。

関連情報