4 ms·
Please please please always quote variable expansion. Just do it everywhere, every time. for i in “${foo[@]}”; do
by stouset 3y ago
Please please please always quote variable expansion. Just do it everywhere, every time.
for i in “${foo[@]}”; do
- pjot 3y agoTo illustrate why, consider a file name with spaces. filename="my file.txt" cat $filename # Incorrect: Tries to 'cat' two files: 'my' and 'file.txt' cat "$filename" # Correct: Treats 'my file.txt' as one file
- mgdlbp 3y agoAdditionally, $ f=-x $ cat "$f" cat: invalid option -- 'x' $ cat -- "$f" cat: -x: No such file or directory # ^-- correct, but: $ f=- $ cat -- "$f" reading stdin... reading stdin... ^C $ f=./- $ cat -- "$f" cat: ./-: No such file or directory ...better to glob with ./* than *
- pjot 3y agoAlso for sanitizing user input. input=$1 # User input, potentially dangerous rm $input # Incorrect: Risky if input contains something like '*' rm "$input" # Correct: Safer, treats the user input as a single item
- akho 3y agoOr use Fish.
- rockwotj 3y agoOr python…
- fragmede 3y agopython is unbelievably awkward for shell scripting though
- vlovich123 3y agoI think with the cmd package it’s not actually that bad and quite ergonomic. Ymmv
- duskwuff 3y agoDo you mean this cmd package? https://docs.python.org/3/library/cmd.html https://docs.python.org/3/library/cmd.html If so, that's entirely orthogonal to the problem. cmd is for writing the interactive "front end" to a command-line interpreter; it doesn't help at all in writing Python scripts to replace shell scripts (which typically run with no interactive interface at all). The sort of problem I think fragmede is alluding to is that of writing Python code to emulate a shell script construct like: some-command 2>&1 | LANG=C sort | uniq -c | wc -l e.g. constructing pipelines of external commands. It's certainly possible to do this in Python, but I'm not aware of any way that'd be anywhere near as concise as the shell syntax.
- js2 3y agoI really don't find using subprocess all that tedious personally. I usually have one helper function around `subproces.run` called `runx` that adds a little sugar. But if you really want something more ergonomic, there's sh: https://pypi.org/project/sh/ https://pypi.org/project/sh/
- duskwuff 3y agosubprocess doesn't make it easy to construct pipelines -- it's possible, but involves a lot of subprocess.Popen(..., stdin=subprocess.PIPE, stdout=subprocess.PIPE) and cursing. The "sh" module doesn't support it at all; each command runs synchronously.
- vlovich123 3y agoIncorrect. https://sh.readthedocs.io/en/latest/sections/piping.html https://sh.readthedocs.io/en/latest/sections/piping.html Just add `_piped=True` to the launch arguments and it'll work as expected where it won't fully buffer the output & wait for the command to complete.
- shmerl 3y agoTrue, true. I don't worry about it for explicitly simple indexes because too many quotes are ugly. But in general it's completely right.