¿Cómo devuelvo octal de la expansión aritmética de Bash?

¿Cómo devuelvo octal de la expansión aritmética de Bash?

Como se explica claramente en la documentación de Bash sobrearitmética de shell, si antepones un número con a 0dentro de una expresión de expansión aritmética (p.ej, $(( expr ))), se trata como octal. De manera similar, puedes usar b#npara un número nen 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.cnferan 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 +0044es probablemente más limpio y más portátil, ya que statlas 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 printfcon la %ocadena 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 printfen absoluto. Si lo único que me importa es sicualquierde los bits en bitmaskfueron 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! "

información relacionada