ls -l出力形式をchmod形式に変換します


17

次の出力があるとしますls -l

drwxr-xr-x 2 root root 4096 Apr  7 17:21 foo

これを使用する形式に自動的に変換するにはどうすればよいchmodですか?

例えば:

$ echo drwxr-xr-x | chmod-format
755

OS X 10.8.3を使用しています。


2
でもっと簡単にstat。あなたはそれを手に入れましたか?(これはGNUツールであるため、ほとんどがLinuxではなくUnixで利用可能です。)
manatwork

@manatwork stat fooはを与え16777219 377266 drwxr-xr-x 119 Tyilo staff 0 4046 "Apr 7 17:49:03 2013" "Apr 7 18:08:31 2013" "Apr 7 18:08:31 2013" "Nov 25 17:13:52 2012" 4096 0 0 /Users/Tyiloます。私はそれを見ません755
ティロ

回答:


24

一部のシステムには、ファイルのアクセス許可を数字で表示するコマンドがありますが、残念ながら、移植性はありません。

zsh持っているstat(別名zstatで)組み込みstatモジュール:

zmodload zsh/stat
stat -H s some-file

すると、mode中にある$s[mode]が、種類+パーマでモード、です。

許可を8進数で表現するには、次のものが必要です。

perms=$(([##8] s[mode] & 8#7777))

BSD(Apple OS / Xを含む)にもstatコマンドがあります。

mode=$(stat -f %p some-file)
perm=$(printf %o "$((mode & 07777))"

GNU find(1990年まで遡り、おそらくそれ以前)は、許可を8進数として出力できます。

find some-file -prune -printf '%m\n'

その後(2001年、zsh stat(1997)よりずっと後、しかしBSD stat(2002)より前)、GNU statコマンドが導入されました。

stat -c %a some-file

それらのずっと前に、IRIXにはすでに別の構文を持つstatコマンド(1994年のIRIX 5.3に既にありました)がありました。

stat -qp some-file

繰り返しますが、標準のコマンドがない場合、移植性の最善の策は以下を使用することperlです:

perl -e 'printf "%o\n", (stat shift)[2]&07777' some-file

15

オプションstatを使用して、GNU に許可を8進数形式で出力するように依頼でき-cます。からman stat

       -c  --format=FORMAT
              use the specified FORMAT instead of the default; output a
              newline after each use of FORMAT
⋮
       %a     access rights in octal
⋮
       %n     file name

あなたの場合:

bash-4.2$ ls -l foo
-rw-r--r-- 1 manatwork manatwork 0 Apr  7 19:43 foo

bash-4.2$ stat -c '%a' foo
644

またはstat、有効なコマンドとしての出力をフォーマットすることで自動化することもできます。

bash-4.2$ stat -c "chmod %a '%n'" foo
chmod 644 'foo'

bash-4.2$ stat -c "chmod %a '%n'" foo > setpermission.sh

bash-4.2$ chmod a= foo

bash-4.2$ ls -l foo
---------- 1 manatwork manatwork 0 Apr  7 19:43 foo

bash-4.2$ sh setpermission.sh 

bash-4.2$ ls -l foo
-rw-r--r-- 1 manatwork manatwork 0 Apr  7 19:43 foo

上記のソリューションは、ワイルドカードを使用している場合、複数のファイルでも機能します。

stat -c "chmod -- %a '%n'" -- *

空白文字を含むファイル名では正しく動作しますが、一重引用符を含むファイル名では失敗します。


2
私にstat-c選択肢がありません。OS X 10.8.3を使用しています。
ティロ

情報をありがとう、@ Tyilo。そして申し訳ありませんが、私はOS Xのツールを手伝うことができません。
マナトワーク

Mac OS Xは、出力形式を指定するための-fフラグを持っているのmanページ^ W ^ W ^ W STAT(1)、例えばを読んで試してみてくださいstat -f 'chmod %p "%N"'
gelraen

11

記号表記から8進表記に変換するために、私はかつて思いつきました:

chmod_format() {
  sed 's/.\(.........\).*/\1/
    h;y/rwsxtSTlL-/IIIIIOOOOO/;x;s/..\(.\)..\(.\)..\(.\)/|\1\2\3/
    y/sStTlLx-/IIIIIIOO/;G
    s/\n\(.*\)/\1;OOO0OOI1OIO2OII3IOO4IOI5IIO6III7/;:k
    s/|\(...\)\(.*;.*\1\(.\)\)/\3|\2/;tk
    s/^0*\(..*\)|.*/\1/;q'
}

拡張:

#! /bin/sed -f
s/.\(.........\).*/\1/; # extract permissions and discard the rest

h; # store a copy on the hold space

# Now for the 3 lowest octal digits (rwx), translates the flags to
# binary where O means 0 and I means 1.
# l, L are for mandatory locking (a regular file that has 02000 on
# and not 010 on some systems like Linux). Some ls implementations
# like GNU ls confusingly use S there like for directories even though 
# it has nothing to do with setgid in that case. Some ls implementations 
# use L, some others l (against POSIX which requires an uppercase
# flag for extra flags when the execution bit is not set).
y/rwsxtSTlL-/IIIIIOOOOO/

x; # swap hold and pattern space, to do a second processing on those flags.

# now only consider the "xXlLsStT" bits:
s/..\(.\)..\(.\)..\(.\)/|\1\2\3/

y/sStTlLx-/IIIIIIOO/; # make up the 4th octal digit as binary like before

G; # append the hold space so we now have all 4 octal digits as binary

# remove the extra newline and append a translation table
s/\n\(.*\)/\1;OOO0OOI1OIO2OII3IOO4IOI5IIO6III7/

:k
  # translate the OOO -> 0 ... III -> 7 in a loop
  s/|\(...\)\(.*;.*\1\(.\)\)/\3|\2/
tk

# trim leading 0s and our translation table.
s/^0*\(..*\)|.*/\1/;q

これは、ls -l1つのファイルの出力から8進数を返します。

$ echo 'drwSr-sr-T' | chmod_format
7654

出力でこれを使用して、dpkgアクセス許可を「インストール済み」に戻しました。どのコマンドが許可文字列を生成したかに関係なく、文字通りの質問に答えてくれてありがとう。
HiTechHiTouch

3

shの下のMac上のこのコマンド

stat -f "%Lp %N" your_files

数値の許可のみが必要な場合は、%Lpのみを使用します。

例えば:

stat -f "%Lp %N" ~/Desktop
700 Desktop

700はchmodで使用できる数値の許可であり、Desktopはファイル名です。


2

OPの試みに触発された、質問Y質問Xを無視)への回答を次に示します。

#!/bin/bash
LC_COLLATE=C
while read ls_out
do
        extra=0
        perms=0
        for i in {1..9}
        do
                # Shift $perms to the left one bit, so we can always just add the LSB.
                let $((perms*=2))
                this_char=${ls_out:i:1}
                # If it's different from its upper case equivalent,
                # it's a lower case letter, so the bit is set.
                # Unless it's "l" (lower case L), which is special.
                if [ "$this_char" != "${this_char^}" ]  &&  [ "$this_char" != "l" ]
                then
                        let $((perms++))
                fi
                # If it's not "r", "w", "x", or "-", it indicates that
                # one of the high-order (S/s=4000, S/s/L/l=2000, or T/t=1000) bits
                # is set.
                case "$this_char" in
                  ([^rwx-])
                        let $((extra += 2 ** (3-i/3) ))
                esac
        done
        printf "%o%.3o\n" "$extra" "$perms"
done

上記にはいくつかのバシズムが含まれています。次のバージョンはPOSIXに準拠しているようです。

#!/bin/sh
LC_COLLATE=C
while read ls_out
do
        extra=0
        perms=0
        for i in $(seq 1 9)
        do
                # Shift $perms to the left one bit, so we can always just add the LSB.
                : $((perms*=2))
                this_char=$(expr "$ls_out" : ".\{$i\}\(.\)")
                # Lower case letters other than "l" indicate that permission bits are set.
                # If it's not "r", "w", "x", or "-", it indicates that
                case "$this_char" in
                  (l)
                        ;;
                  ([a-z])
                        : $((perms+=1))
                esac
                # If it's not "r", "w", "x", or "-", it indicates that
                # one of the high-order (S/s=4000, S/s/L/l=2000, or T/t=1000) bits
                # is set.
                case "$this_char" in
                  ([!rwx-])
                        : $((extra += 1 << (3-i/3) ))
                esac
        done
        printf "%o%.3o\n" "$extra" "$perms"
done

ノート:

  • LC_COLLATE=CASCII順序を使用するものとして扱う文字列の範囲のパターンにシェルを伝え、そう[a-e]と同等です[abcde]。一部のロケール(en_USなど)では、[a-e]同等[aAbBcCdDeE] (つまり[abcdeABCDE])または多分[abcdeABCD]なぜbashのcaseステートメントで大文字と小文字が区別されないのかを参照してください…?
  • 2番目のバージョン(POSIX準拠バージョン):

    • 最初のcaseステートメントは書き直すことができます。

              case "$this_char" in
                ([a-km-z])
                      : $((perms+=1))
              esac
      

      しかし、私がそれを持っている方法l は、それが異なるように処理されている手紙であることがわかりやすくなると思います。または、次のように書き換えることもできます。

              case "$this_char" in
                ([rwxst])
                      : $((perms+=1))
              esac
      

      以来rwxs、およびtこれまでに(以外のモード列に表示されます文字だけですl)。

    • 2番目のcaseステートメントは書き直すことができます。

              case "$this_char" in
                ([rwx])
                      ;;
                ([A-Za-z])
                      : $((extra += 1 << (3-i/3) ))
               esac
      

      モードビットの指定には文字のみが有効であるというルールを実施します。(対照的に、完全なスクリプトのより簡潔なバージョンは遅延型であり-rw@rw#rw%rwSrwSrwT。と同等のものとして受け入れられ  ます。)あるいは、書き換えることもできます。

              case "$this_char" in
                ([SsTtLl])
                      : $((extra += 1 << (3-i/3) ))
              esac
      

      以来SsTtL、およびlこれまでのモード(以外の文字列に表示されます文字だけありrwx)。

使用法:

$ echo drwxr-xr-x | chmod-format
0755
$ echo -rwsr-sr-x | chmod-format
6755
$ echo -rwSr-Sr-- | chmod-format
6644
$ echo -rw-r-lr-- | chmod-format
2644
$ echo ---------- | chmod-format
0000

そして、はい、でecho始まる可能性のあるテキストには使用しないほうが良いことを知ってい-ます。質問の使用例をコピーしたかっただけです。注、明らかに、これは0番目の文字を無視していること(すなわち、リードd/ b/ c/ -/ l/ p/ s/ D)と10日(+/ ./ @)。のメンテナーは、3番目、6番目、または9番目の位置で/ または/ を有効な文字としてls決して定義しないことを前提としています (もしそうなら、棒でbeatられるべきです)。rRwW


また、/ varの下にあるすべてのファイルのデフォルトのグループ/ユーザー所有権を復元する方法の下 に、casによって次のコードが見つかりました:

        let perms=0

        [[ "${string}" = ?r???????? ]]  &&  perms=$(( perms +  400 ))
        [[ "${string}" = ??w??????? ]]  &&  perms=$(( perms +  200 ))
        [[ "${string}" = ???x?????? ]]  &&  perms=$(( perms +  100 ))
        [[ "${string}" = ???s?????? ]]  &&  perms=$(( perms + 4100 ))
        [[ "${string}" = ???S?????? ]]  &&  perms=$(( perms + 4000 ))
        [[ "${string}" = ????r????? ]]  &&  perms=$(( perms +   40 ))
        [[ "${string}" = ?????w???? ]]  &&  perms=$(( perms +   20 ))
        [[ "${string}" = ??????x??? ]]  &&  perms=$(( perms +   10 ))
        [[ "${string}" = ??????s??? ]]  &&  perms=$(( perms + 2010 ))
        [[ "${string}" = ??????S??? ]]  &&  perms=$(( perms + 2000 ))
        [[ "${string}" = ???????r?? ]]  &&  perms=$(( perms +    4 ))
        [[ "${string}" = ????????w? ]]  &&  perms=$(( perms +    2 ))
        [[ "${string}" = ?????????x ]]  &&  perms=$(( perms +    1 ))
        [[ "${string}" = ?????????t ]]  &&  perms=$(( perms + 1001 ))
        [[ "${string}" = ?????????T ]]  &&  perms=$(( perms + 1000 ))

私はこのコードをテストしましたが(完全ではありません)、認識されないlL6番目の位置にあるという事実を除いて、動作するようです。ただし、この答えは単純さと明快さの点では優れていますが、実際は短い(ループのコードのみを-rwxrwxrwxカウントし、コメントをカウントせずに単一の文字列を処理するコード)ため、さらに短くすることができます交換することにより で。if condition; then …condition && …


もちろん、の出力を解析lsするべきではありません


@StéphaneChazelas:OK、私は言って#!/bin/shからいくつかのバシズムを使った。おっとっと。しかし、あなたはカップルを見逃しました:そしてPOSIXでもないようです(スタンダードはまったく言及しておらず、そしてsquirrelly on および)。逆に、使用しませんでした。これはcasの回答にのみ表示ますここから引用ました。また、私の答えは「l」と「L」を処理し、casの答えは処理しないという事実をすでに指摘しました。$(( variable++ ))$(( number ** number ))**++-- [[…]]
スコット

l / Lについては申し訳ありません[[、読みすぎです。はい、-と++はPOSIXではありません。POSIXでは、シェルでそれらを実装できます。つまり、デクリメント操作を意味するので$((- -a))はなく、二重否定が必要な場合は記述する必要があります$((--a))
ステファンシャゼル

seqこれはPOSIXコマンドではないことに注意してください。exprを避けるために$ {var#?}演算子を使用できる場合があります。LC_COLLATEはLC_ALL上書きしませんではないこと
ステファンChazelas

@StéphaneChazelas:OK、あなたは今再びcasの答えについて話していますよね?彼は、10進数演算を使用して8進数のように見える文字列を作成する「遅延」アプローチを取っています。彼のすべてのステップ値(4000、2000、1000、400、200、100、40、20、および10)は10進数であることに注意してください。しかし、8「」や9「」はなく7、小数点以下の桁数よりも多くを取得する方法がないため、彼はシャレードを引っ張ることができます。……………………(このコメントは、消えたステファンシャゼラスのコメントに対する応答です。)
スコット

はい、後で気づいたので、コメントを削除しました。
ステファンシャゼル

1

あるファイルから許可を取得し、別のファイルにも許可を与えることが目標である場合、GNUにchmodそのための「参照」オプションが既にあります


OPは、彼がApple OS / Xを使用しているchmodと述べたので、GNUではchmodありません。
ステファンシャゼル

ああ、私は彼らがプラットフォームを言う他の答えについてのコメントを見ています。鉱山はかかわらず、GNUを言及するだけでなく、あなたは、Mac OS X上のGNUユーティリティ得ることができます
Bratchley

0

別の方法として、アクセス許可を保存しておき、後で、または別のファイルにsetfacl/getfacl復元する場合は、を使用し、ボーナスとして(POSIXドラフト)ACLも復元します。

getfacl some-file > saved-perms
setfacl -M saved-perms some-other-file

(Solarisでは、の-f代わりに使用します-M)。

ただし、一部のBSDで使用できますが、ACL chmodのみを操作するApple OS / Xでは使用できません。


0

Mac OS X(10.6.8)では、使用する必要がありますstat -f format(実際にはNetBSD / FreeBSDであるためstat)。

# using Bash

mods="$(stat -f "%p" ~)"    # octal notation
mods="${mods: -4}"
echo "$mods"

mods="$(stat -f "%Sp" ~)"  # symbolic notation
mods="${mods: -9}"
echo "$mods"

によって生成さls -lれたシンボリック許可文字列を8進数に変換するだけ(シェル組み込みコマンドのみを使用)は、showperm.bashを参照してください。

# from: showperm.bash
# usage: showperm modestring
#
# example: showperm '-rwsr-x--x'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.