Como se explica claramente en la documentación de Bash sobrearitmética de shell, si antepones un número con a 0
dentro de una expresión de expansión aritmética (p.ej, $(( expr ))
), se trata como octal. De manera similar, puedes usar b#n
para un número n
en base b
.
Sin embargo, independientemente de la base que utilices para la aritméticaadentrola expresión, el valor siempre se devuelve como base 10. ¿Cómo puedodevolveroctal a partir del resultado de una expansión aritmética?
Mi caso de uso original para esto fue advertir a un usuario que los permisos ~/.my.cnf
eran demasiado laxos (legibles para el grupo o para el mundo) al unir los bits de permiso del archivo con una máscara de bits, pero luego decidí que probar la salida de find ~/.my.cnf -perm +0044
es probablemente más limpio y más portátil, ya que stat
las cadenas de formato no son estándar entre macOS/BSD y Linux. Sin embargo, la pregunta persiste.
Respuesta1
Aquí hay un dato que encontré en un comentario enotro hilo SE: puedes usarlo printf
con la %o
cadena de formato (octal).
Un ejemplo práctico:
# figure out stat(1) flags based on OS
if [[ $(uname -s) == Linux ]]; then PERMS='-c %a' else PERMS='-f %Lp'; fi
stat $PERMS ~/.my.cnf
# result: 600 (not group/world readable)
# permission bits if group/world readable
bitmask=044
perm=$(stat $PERMS ~/.my.cnf)
printf "%o\n" $(( 0$perm & 0$bitmask ))
# result: 0
# now make the file group-readable and try again
chmod 640 ~/.my.cnf
perm=$(stat $PERMS ~/.my.cnf)
printf "%o\n" $(( 0$perm & 0$bitmask ))
# result: 40
Bono: otras soluciones
Si no quieroverLos bits de permisos en octal, podría lograr mi objetivo original sin usarlos printf
en absoluto. Si lo único que me importa es sicualquierde los bits en bitmask
fueron configurados, simplemente probar si el resultado es distinto de cero es suficiente:
if (( 0$perm & 0$bitmask )); then
echo "Permissions $perm are too lax." >&2
fi
Si quisieras saber sitodose configuraron los bits bitmask
, luego compare el resultado de unirlos con la máscara de bits, algo como esto:
(( (0777 & 0066) == 0066 )) && echo "Oh noes, group AND world writable! "