Bash の算術展開から 8 進数を返すにはどうすればいいですか?

Bash の算術展開から 8 進数を返すにはどうすればいいですか?

Bashのドキュメントに明確に記載されていますシェル演算0算術展開式内で数値の前に を付けると(例えば$(( expr ))) の場合は 8 進数として扱われます。同様に、 を基数とするb#n数値に使用できます。nb

しかし、計算に使用する基数に関係なく内部式では、値は常に10進数として返されます。戻る算術展開の結果から 8 進数を取得しますか?

~/.my.cnfこれを最初に使用した目的は、ファイルの権限ビットをビットマスクで AND 演算して、権限がfind ~/.my.cnf -perm +0044緩すぎる (グループまたはワールドが読み取り可能) ことをユーザーに警告することでしたが、後に、macOS/BSD と Linux の間でフォーマット文字列が標準ではないため、の出力をテストする方がおそらくよりクリーンで移植性が高いと判断しましたstat。しかし、疑問は残ります。

答え1

これは私が偶然コメントで見つけたちょっとした情報です別のSEスレッド: (8 進) フォーマット文字列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

ボーナス: その他の解決策

やりたくないなら見るパーミッションビットを8進数で表すと、printfまったく使用せずに当初の目的を達成できます。私が気にするのは、どれでものビットがbitmask設定されている場合は、結果がゼロ以外であるかどうかをテストするだけで十分です。

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

もしあなたが知りたいなら全てのビットがbitmask設定されている場合は、それらの AND 演算の結果をビットマスクと比較します。次のようになります。

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

関連情報