Node-RED で exec ノードから Linux のファイル一覧表示コマンド ls -la の結果をパースして JSON で取得するメモ

Node-RED で exec ノードから Linux のファイル一覧表示コマンド ls -la の結果をパースして JSON で取得するメモです。

背景

Raspberry Pi や Linux の環境で file ノードで読み書き削除ができるのですが、もう少し発展するとすぐファイル一覧を元に何かしたくなるので、ファイル一覧表示コマンド ls -la の結果をパースして JSON で取得するようにしてみました。

フロー

nodered-parse-linux-ls-command_03.png

実際のフローはこんな感じです。Raspberry Pi や Linux の環境で動かしてる Node-RED で動きます。Windows の WSL 環境で動かした Linux Ubuntu で確認してます。

JSON フローはこちらです。

[{"id":"42b7a0752c882a4c","type":"exec","z":"34872961800da817","command":"ls -la  \"/root\"","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":390,"y":160,"wires":[["7c07f38697db02ea"],[],[]]},{"id":"a4b682bf2b958174","type":"inject","z":"34872961800da817","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":160,"wires":[["42b7a0752c882a4c"]]},{"id":"284ffd78117d0174","type":"debug","z":"34872961800da817","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":840,"y":160,"wires":[]},{"id":"7c07f38697db02ea","type":"function","z":"34872961800da817","name":"ls -la のパース","func":"const stringList = msg.payload;\n\nconst arrList = stringList.split(\"\\n\");\n\n// 3 件削除\narrList.shift(); // 最初の total の行を削除\narrList.shift(); // . の行を削除\narrList.shift(); // .. の行を削除\n\nconst arrParsed = [];\n\narrList.forEach(function (file) {\n\n    const list = file.split(/\\s+/);\n\n    // 最後の空行を無視\n    if (list[0] == \"\") {\n\n    } else {\n\n        const item = {\n            \"flags\": list[0],\n            \"links\": Number(list[1]),\n            \"owner\": list[2],\n            \"group\": list[3],\n            \"size\": Number(list[4]),\n            \"date\": `${list[5]} ${list[6]} ${list[7]}`,\n            \"filename\": list[8]\n        };\n\n        arrParsed.push(item);\n    }\n\n});\n\nmsg.payload = arrParsed;\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":160,"wires":[["284ffd78117d0174"]]}]

フローの仕組み

nodered-parse-linux-ls-command_00.png

exe ノードの中身です。

nodered-parse-linux-ls-command_02.png

このように ls -la “ファイルパス” でファイルリストを取得します。

total 52
drwx------  9 root root 4096 Nov  9 17:05 .
drwxr-xr-x 19 root root 4096 Mar 23 10:17 ..
-rw-------  1 root root 1794 Mar  8 21:03 .bash_history
-rw-r--r--  1 root root 3303 Nov  9 17:01 .bashrc
drwx------  2 root root 4096 Oct 12 11:32 .cache
-rw-r--r--  1 root root   58 Oct 12 11:42 .gitconfig
drwxr-xr-x  3 root root 4096 Oct 12 11:41 .local
-rw-r--r--  1 root root    0 Mar 23 10:18 .motd_shown
drwxr-xr-x  4 root root 4096 Mar 23 10:18 .node-red
drwxr-xr-x  4 root root 4096 Nov  9 17:04 .npm
drwxr-xr-x  8 root root 4096 Nov  9 17:03 .nvm
-rw-r--r--  1 root root  161 Dec  5  2019 .profile
drwx------  2 root root 4096 Oct 12 11:41 .ssh
drwx------  3 root root 4096 Oct 12 11:32 snap

例えば、今回は /root の一覧はこのようになります。

nodered-parse-linux-ls-command_01.png

このデータを function ノードで JSON データに変換します。

const stringList = msg.payload;

const arrList = stringList.split("\n");

// 3 件削除
arrList.shift(); // 最初の total の行を削除
arrList.shift(); // . の行を削除
arrList.shift(); // .. の行を削除

const arrParsed = [];

arrList.forEach(function (file) {

    const list = file.split(/\s+/);

    // 最後の空行を無視
    if (list[0] == "") {

    } else {

        const item = {
            "flags": list[0],
            "links": Number(list[1]),
            "owner": list[2],
            "group": list[3],
            "size": Number(list[4]),
            "date": `${list[5]} ${list[6]} ${list[7]}`,
            "filename": list[8]
        };

        arrParsed.push(item);
    }

});

msg.payload = arrParsed;

return msg;

function ノードの中身の JavaScript です。

この仕組みでファイル一覧を JSON で取得できます。

動かしてみる

nodered-parse-linux-ls-command_04.png

inject ノードをクリックします。

nodered-parse-linux-ls-command_05.png

このようにデバック結果が表示されてファイル一覧が JSON で取得されます!