Как ясно изложено в документации 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
вообще. Если все, что меня волнует, это то,любойбитов в bitmask
were установлены, достаточно просто проверить, является ли результат ненулевым:
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! "