Conforme claramente explicado na documentação do Bash emaritmética de casca, se você prefixar um número com a 0
dentro de uma expressão de expansão aritmética (por exemplo, $(( expr ))
), é tratado como octal. Da mesma forma, você pode usar b#n
para um número n
em base b
.
No entanto, independentemente da base que você usa para a aritméticadentroexpressão, o valor é sempre retornado como base 10. Como faço pararetornaroctal do resultado de uma expansão aritmética?
Meu caso de uso original para isso era avisar um usuário que as permissões nele ~/.my.cnf
eram muito frouxas (legíveis em grupo ou mundialmente) juntando AND os bits de permissão do arquivo com uma máscara de bits, mas mais tarde decidi que testar a saída de find ~/.my.cnf -perm +0044
é provavelmente mais limpo e portátil, já que stat
as strings de formato não são padrão entre macOS/BSD e Linux. No entanto, a questão permanece.
Responder1
Aqui está um boato que descobri em um comentário emoutro tópico SE: você pode usar apenas printf
com a %o
string de formato (octal).
Um exemplo prático:
# 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
Bônus: outras soluções
Se eu não quiserveros bits de permissão em octal, eu poderia atingir meu objetivo original sem usar printf
nada. Se tudo que me importa é sequalquerdos bits no foram definidos bitmask
, apenas testar se o resultado é diferente de zero é suficiente:
if (( 0$perm & 0$bitmask )); then
echo "Permissions $perm are too lax." >&2
fi
Se você quisesse saber setodosos bits bitmask
foram definidos e, em seguida, compare o resultado do AND entre eles e a máscara de bits, algo assim:
(( (0777 & 0066) == 0066 )) && echo "Oh noes, group AND world writable! "