Como retorno octal da expansão aritmética do Bash?

Como retorno octal da expansão aritmética do Bash?

Conforme claramente explicado na documentação do Bash emaritmética de casca, se você prefixar um número com a 0dentro de uma expressão de expansão aritmética (por exemplo, $(( expr ))), é tratado como octal. Da mesma forma, você pode usar b#npara um número nem 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.cnferam 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 statas 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 printfcom a %ostring 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 printfnada. 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 bitmaskforam 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! "

informação relacionada