Voici une réponse à la question Y (en ignorant la question X ), inspirée de la tentative du PO:
#!/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
Ce qui précède contient quelques bashismes. La version suivante semble être compatible 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
Remarques:
Usage:
$ 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
Et, oui, je sais qu'il vaut mieux ne pas utiliser echo
avec du texte qui pourrait commencer -
; Je voulais juste copier l'exemple d'utilisation de la question. Notez, bien entendu, que cela ignore le 0ème caractère (c'est-à-dire le premier d
/ b
/ c
/ -
/ l
/ p
/ s
/ D
) et le 10ème ( +
/ .
/ @
). Il suppose que les mainteneurs de ls
ne définiront jamais
r
/ R
ou w
/ W
comme des caractères valides en troisième, sixième ou neuvième position (et, s'ils le font, ils devraient être battus avec des bâtons ).
En outre, je viens de trouver le code suivant, par cas , sous
Comment restaurer la propriété par défaut du groupe / utilisateur de tous les fichiers sous / 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 ))
J'ai testé ce code (mais pas complètement), et il semble fonctionner, sauf qu'il ne reconnaît pas l
ou L
en sixième position. Notez, cependant, que bien que cette réponse soit supérieure en termes de simplicité et de clarté, la mienne est en fait plus courte (en comptant uniquement le code à l' intérieur de la boucle; le code qui gère une seule -rwxrwxrwx
chaîne, sans compter les commentaires), et elle pourrait être encore plus courte en remplaçant
par .if condition; then …
condition && …
Bien sûr, vous nels
devez pas analyser la sortie de .
stat
. L'avez vous? (C'est un outil GNU, donc principalement disponible sur Linux, pas sur Unix.)