Inilah jawaban untuk pertanyaan Y (mengabaikan pertanyaan X ), terinspirasi oleh upaya OP:
#!/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
Di atas mengandung beberapa bashism. Versi berikut ini tampaknya kompatibel dengan 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
Catatan:
Pemakaian:
$ 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
Dan, ya, saya tahu lebih baik tidak menggunakan echoteks yang mungkin dimulai dengan -; Saya hanya ingin menyalin contoh penggunaan dari pertanyaan. Perhatikan, jelas, bahwa ini mengabaikan karakter 0 (yaitu, yang memimpin d/ b/ c/ -/ l/ p/ s/ D) dan 10 ( +/ ./ @). Ini mengasumsikan bahwa pengelola lstidak akan pernah mendefinisikan
r/ Ratau w/ Wsebagai karakter yang valid di posisi ketiga, keenam, atau kesembilan (dan, jika mereka melakukannya, mereka harus dipukuli dengan tongkat ).
Juga, saya baru saja menemukan kode berikut, menurut cas , di bawah
Cara mengembalikan kepemilikan grup / pengguna default semua file di bawah / var :
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 ))
Saya telah menguji kode ini (tetapi tidak sepenuhnya), dan tampaknya berhasil, kecuali kenyataan bahwa ia tidak mengenali latau berada Ldi posisi keenam. Perhatikan, meskipun jawaban ini lebih unggul dalam hal kesederhanaan dan kejelasan, saya sebenarnya lebih pendek (hanya menghitung kode di dalam loop; kode yang menangani -rwxrwxrwxstring tunggal , tidak menghitung komentar), dan itu bisa dibuat lebih pendek dengan mengganti
dengan .if condition; then …condition && …
Tentu saja, Anda tidak perlu menguraikan outputls .
stat. Apakah kamu memilikinya? (Ini alat GNU, jadi sebagian besar tersedia di Linux, bukan di Unix.)