Not laughing.
It's messy for Node-red to rely on an external script file.
You can define and execute a script entirely within Node-red, While I am happy with simple pipelines in the exec node, for slightly more complex scripts I do it like this: (Sorry my example uses RPi specific commands)
[{"id":"88c26d2f3ed7f321","type":"group","z":"db04fd79f3a93d19","name":"A non-interactive Bash script","style":{"label":true},"nodes":["106bb647629b1f06","b0369609aa7d7ab6","513da4b56a8bb46e","686db71073ded405"],"x":54,"y":1111.5,"w":592,"h":97},{"id":"106bb647629b1f06","type":"inject","z":"db04fd79f3a93d19","g":"88c26d2f3ed7f321","name":"Go","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"go","payloadType":"str","x":150,"y":1160,"wires":[["686db71073ded405"]]},{"id":"b0369609aa7d7ab6","type":"exec","z":"db04fd79f3a93d19","g":"88c26d2f3ed7f321","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":430,"y":1160,"wires":[["513da4b56a8bb46e"],["513da4b56a8bb46e"],[]]},{"id":"513da4b56a8bb46e","type":"debug","z":"db04fd79f3a93d19","g":"88c26d2f3ed7f321","name":"output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":1160,"wires":[]},{"id":"686db71073ded405","type":"template","z":"db04fd79f3a93d19","g":"88c26d2f3ed7f321","name":"Bash script","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"# Discover and format CPU frequency & temperature\n\n# vcgencmd measure_clock_arm returns eg \"frequency(48)=600169920\"\nFREQ=$(vcgencmd measure_clock arm | sed -E 's/(.*=)(.*)/\\2/')\nFREQ=$[FREQ / 1000000]\n\n# vcgencmd measure_temp returns eg \"temp=30.6'C\"\nTEMP=$(vcgencmd measure_temp | sed -E 's/(.*=)([0-9]*)(.*)/\\2/')\nprintf \"CPU %d MHz, %d °C\" $FREQ $TEMP","output":"str","x":290,"y":1160,"wires":[["b0369609aa7d7ab6"]]}]
And an example passing parameters
[{"id":"2954d59d172778e7","type":"group","z":"db04fd79f3a93d19","name":"Passing parameters to a Bash script as environment variables","style":{"label":true},"nodes":["4d82f796d89d6044","f66b1b60040f4067","d9290c0c62e0f7c0","cc39d099b49cf9fe","af8dbd68b05f6313","bb3f370af4971b28"],"x":34,"y":951.5,"w":772,"h":129.5},{"id":"4d82f796d89d6044","type":"inject","z":"db04fd79f3a93d19","g":"2954d59d172778e7","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"/home/pi","payloadType":"str","x":140,"y":1000,"wires":[["f66b1b60040f4067"]]},{"id":"f66b1b60040f4067","type":"template","z":"db04fd79f3a93d19","g":"2954d59d172778e7","name":"Bash script ","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"DIR={{{payload}}}\nsudo du -sm $DIR | awk '\n{printf \"{\\\"directory\\\": { \\\"name\\\": \\\"%s\\\", \\\"diskuse\\\": %d, \\\"units\\\": \\\"MB\\\"}}\", $2, $1}'","output":"str","x":290,"y":1000,"wires":[["cc39d099b49cf9fe","d9290c0c62e0f7c0"]]},{"id":"d9290c0c62e0f7c0","type":"exec","z":"db04fd79f3a93d19","g":"2954d59d172778e7","command":"","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":450,"y":1000,"wires":[["bb3f370af4971b28"],[],[]]},{"id":"cc39d099b49cf9fe","type":"debug","z":"db04fd79f3a93d19","g":"2954d59d172778e7","name":"Full Script","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":460,"y":1040,"wires":[]},{"id":"af8dbd68b05f6313","type":"debug","z":"db04fd79f3a93d19","g":"2954d59d172778e7","name":"output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":1000,"wires":[]},{"id":"bb3f370af4971b28","type":"json","z":"db04fd79f3a93d19","g":"2954d59d172778e7","name":"","property":"payload","action":"","pretty":false,"x":590,"y":1000,"wires":[["af8dbd68b05f6313"]]}]