node.jsのfs.stat, fs.lstat, fs.fstatが返すfs.Statsクラスには、その名もずばりのmodeというpropertyがあるのですが、この値からファイルのパーミッションを直接知る手段が標準では用意されていません。1 まーそんなに難しい話ではないので、頭の体操がてらちょちょいとコードを書いてみましょう。
まず、fs.Stats.modeの値の正体ですが、これはそのまんまstat(), lstat(), fstat()が返すstat構造体のst_modeフィールドの値と同じようなので、下位の(8進数で)3桁をマスクしてやれば通常のパーミッションが値として取得できます。
javascriptでのbit演算はCと同じで、&がbit-wise ANDなのでmode & mask
とすればOKです。
ただし、modeの値は10進数だけど、我々が普段使っているumask値は8進数なので、この変換を行う必要があります。
といっても、parseInt関数を使えばOKでparseInt(777,8)
で下位3桁のmaskが作れます。
もしスティッキービットとかも必要だったら7777にすればOKです。
これで、ファイルのパーミッションが10進数の整数値として取得できたので、最後に8進数の表現に直します。 こちらも、javascriptの標準の範囲内でできてしまって、toString()に引数として8を渡してあげればOKです。
この3つを組み合わせて、カレントディレクトリのファイルのパーミッションを8進数で表示するプログラムを作るとこんな感じになります。
const {promisify} = require('util'); const fs = require('fs'); async function getFileMode(filename){ let stats = await promisify(fs.stat)(filename); return (stats.mode & parseInt(777, 8)).toString(8); } async function main(){ let files = await promisify(fs.readdir)('./'); files.forEach(async (file)=>{ console.log(file, await getFileMode(file)); }); } main();
テスト結果
$ ls -l . total 8 ---xrwxrwx 1 so5 staff 0 12 13 23:06 file177 --w-rwxrwx 1 so5 staff 0 12 13 23:07 file277 --wxrwxrwx 1 so5 staff 0 12 13 23:07 file377 -r--rwxrwx 1 so5 staff 0 12 13 23:06 file477 -r-xrwxrwx 1 so5 staff 0 12 13 23:08 file577 -rw-rwxrwx 1 so5 staff 0 12 13 23:07 file677 -rwx--xrwx 1 so5 staff 0 12 13 23:11 file717 -rwx-w-rwx 1 so5 staff 0 12 13 23:11 file727 -rwx-wxrwx 1 so5 staff 0 12 13 23:11 file737 -rwxr--rwx 1 so5 staff 0 12 13 23:11 file747 -rwxr-xrwx 1 so5 staff 0 12 13 23:11 file757 -rwxrw-rwx 1 so5 staff 0 12 13 23:11 file767 -rwxrwx--x 1 so5 staff 0 12 13 23:11 file771 -rwxrwx-w- 1 so5 staff 0 12 13 23:11 file772 -rwxrwx-wx 1 so5 staff 0 12 13 23:11 file773 -rwxrwxr-- 1 so5 staff 0 12 13 23:11 file774 -rwxrwxr-x 1 so5 staff 0 12 13 23:11 file775 -rwxrwxrw- 1 so5 staff 0 12 13 23:11 file776 -rwxrwxrwx 1 so5 staff 0 12 13 23:11 file777 -rw-r--r-- 1 so5 staff 378 12 13 23:35 test.js $ node test.js file177 177 file277 277 file377 377 file477 477 file577 577 file677 677 file717 717 file727 727 file737 737 file747 747 file757 757 file767 767 file771 771 file772 772 file773 773 file774 774 file775 775 file776 776 file777 777 test.js 644
10進数->8進数(もちろん2進数や16進数も)の変換にtoStringを使うっていうのは違和感がありますが、JSだと10進数以外の整数は文字列として表すしかないから当然といえば当然かもしれませんが。