Как вернуть восьмеричное число из арифметического расширения Bash?

Как вернуть восьмеричное число из арифметического расширения Bash?

Как ясно изложено в документации Bashарифметика оболочки, если вы добавляете к числу префикс a 0в выражении арифметического расширения (например, $(( expr ))), он рассматривается как восьмеричный. Аналогично, вы можете использовать b#nдля числа nв базе b.

Однако, независимо от того, какую основу вы используете для арифметики,внутривыражение, значение всегда возвращается как основание 10. Как мневозвращатьсявосьмеричное число из результата арифметического разложения?

Мой первоначальный вариант использования этого состоял в том, чтобы предупредить пользователя о том, что разрешения на его файл ~/.my.cnfслишком слабые (доступны для чтения всем или группе), с помощью AND битов разрешений файла с битовой маской, но позже я решил, что тестирование вывода, find ~/.my.cnf -perm +0044вероятно, будет более чистым и переносимым, поскольку statстроки формата не являются стандартными между macOS/BSD и Linux. Тем не менее, вопрос остается.

решение1

Вот интересный факт, на который я наткнулся в комментарии веще одна тема SE: можно просто использовать printfсо %oстрокой формата (восьмеричной).

Рабочий пример:

# 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

Бонус: другие решения

Если я не хочувидетьбиты разрешений в восьмеричном формате, я мог бы достичь своей первоначальной цели, не используя printfвообще. Если все, что меня волнует, это то,любойбитов в bitmaskwere установлены, достаточно просто проверить, является ли результат ненулевым:

if (( 0$perm & 0$bitmask )); then
    echo "Permissions $perm are too lax." >&2
fi

Если вы хотите узнать,всебиты bitmaskбыли установлены, затем сравните результат их объединения с битовой маской, примерно так:

(( (0777 & 0066) == 0066 )) && echo "Oh noes, group AND world writable! "

Связанный контент