5 ms·
I've found that every time my bash scripts become sufficiently complex, I end up rewriting them in Python.
by feisuzhu 4y ago
I've found that every time my bash scripts become sufficiently complex, I end up rewriting them in Python.
- m463 4y agothat's exactly what I do, and argparse (I believe the motivation for argbash) helps a lot
- Cheeeetah 4y agoI mainly use Python to handle JSON, while use Shell for other things.
- deleted 4y ago[deleted]
- captnswing 4y agothis ^
- ff317 4y agoYeah, I figure if a bash script goes over ~10-20 lines, or involves really long lines, or quotes within quotes within quotes of different kinds, it's time to move on to Python or similar.
- 3np 4y agoIt'\''s always the quotes.
- vaughan 4y agoTypeScript is now tenable for bash scripts with the fast-starting Bun runtime https://bun.sh/ https://bun.sh/. Before Bun, Node+V8 was just too slow to start. IMHO all scripts should be written in TypeScript...you get typechecking and all the rest of the editing experience. Plus things like Wallaby.js for live coding/testing. My `.bashrc` now just runs a TypeScript script with Bun. Allows you to use proper structure instead of brittle spaghetti stuff. The number of times I'm debugging silly PATH stuff was too much...
- ryapric 4y ago>you get typechecking and all the rest of the editing experience This is true for a number of languages that can also be run without AOT compilation (Go, Rust, etc). This feels like some really weird, incoherent astroturf take for Bun promotion.
- vaughan 4y agoJavaScript was not tenable for scripts with Node.js. Startup time is too slow. Now it is because of Bun. I don't think you can argue with that. Rust isn't a scripting language - too strict, no optional typing, slow compilation.
- c0wb0yc0d3r 4y agoDo you have an example?
- vaughan 4y agoimport {alias, _export, _eval} from './util.js' export default async function config() { git() } function git() { alias({ gpsuom: 'git push --set-upstream origin master', gpsuvm: 'git push --set-upstream vjpr master', gpsu: 'git push --set-upstream', gmvd: 'git merge vjpr/dev', gmvdgp: 'git merge vjpr/dev && git push', gprom: 'git pull --rebase origin master', gpuohm: 'git push origin head:master', gpom: 'git pull origin master', grhh: 'git reset --hard HEAD', gisquash: 'git reset --soft HEAD~$(git rev-list --count HEAD ^master)', gacp: "git add . && git commit --message 'Update' && git push", gacmu: "git add . && git commit --message 'Update'", gacmup: "git add . && git commit --message 'Update' && git push", }) } function brew() { alias('bbrew', 'br') alias({ br: 'HOMEBREW_NO_AUTO_UPDATE=1 brew', // x86_64 ibrew: 'arch -x86_64 /usr/local/bin/brew', abrew: '/opt/homebrew/bin/brew', }) _eval(`$(/opt/homebrew/bin/brew shellenv)`) }
- c0wb0yc0d3r 4y ago
- jen20 4y agoFair - I find that every time a Python program becomes sufficiently complex though (defined as "needs something not in the stdlib of Python 3.6"), I end up rewriting them in Go or Rust ;-)
- vultour 4y agoHonestly, I don't think I found a single case where this was true. Every time I try to rewrite a moderately complex bash script in Python it becomes hundreds or thousands of lines of code dealing with calling external binaries, streams and proper error handling. Perhaps if you're only dealing with text processing it will work, but the moment you start piping together external programs via Python it's all pointless.
- m463 4y agoI think when you have a very-well-written bash script, it starts to get pretty close to python in size, but python wins in readability. A well written bash script will handle errors cleanly, will not die on quoting problems, and can use complex data structures or objects when data handling gets hairy. When you use regexes, letting python use them directly seems to be much cleaner than quoting and passing them to awk/sed/grep or other text processing tools. Additionally, python seems to have libraries to handle all kinds of input like json and csv. One thing that python doesn't do as naturally as bash is invoke commands. For python I usually include some functions to run commands passed as a list, and check the return code or return the output. then 'cmd -f $arg1' becomes myrun('cmd','-f', arg1)
- elmolino89 4y agoStringing up a pipe with a mix of awk, tr, sed, cut, sort, uniq etc. is certainly not more readable than a Python script with comments not invoking any of these but using Python's data structures, or even data frames/SQL.
- iudqnolq 4y agosh is the secret to transliterating bash to python. It's basically bash with proper loops and variables and string operations. import sh names = sh.ls("./src") for name in names: sh.mv(["./src/" + name, "./dst/" + name + ".out"])
- iamjackg 4y ago100% agree. There are some libraries like https://amoffat.github.io/sh/ https://amoffat.github.io/sh/ that aim to make that easier, but they always have some quirks that, funnily enough, are often the corner cases you were hitting in your complicated Bash script in the first place.
- JohnFen 4y agoWhen I'm working on/writing complex bash scripts, it's because the scripts have to run on a variety of different customer machines where Python is not consistently available (let alone being able to count on a particular version) and, if it's not there, cannot be installed. The main advantage of bash is that it exists on just about every unix machine.