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=C
ASCII順序を使用するものとして扱う文字列の範囲のパターンにシェルを伝え、そう[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
以来r
、w
、x
、s
、および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
以来S
、s
、T
、t
、L
、およびl
これまでのモード(以外の文字列に表示されます文字だけありr
、w
とx
)。
使用法:
$ 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られるべきです)。r
R
w
W
また、/ 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 ))
私はこのコードをテストしましたが(完全ではありません)、認識されないl
かL
6番目の位置にあるという事実を除いて、動作するようです。ただし、この答えは単純さと明快さの点では優れていますが、実際は短い(ループ内のコードのみを-rwxrwxrwx
カウントし、コメントをカウントせずに単一の文字列を処理するコード)ため、さらに短くすることができます交換することにより
で。if condition; then …
condition && …
もちろん、の出力を解析ls
するべきではありません。
stat
。あなたはそれを手に入れましたか?(これはGNUツールであるため、ほとんどがLinuxではなくUnixで利用可能です。)