Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tool to automatically rewrite a bash script with proper quoting?

I'm contemplating to make all bash scripts of a large codebase shellcheck compliant, but the task is overwhelming, because too many developers have historically ignored rule number one of all shell scripting: always use quotes.

It would be helpful if there was a tool that could fix at least the quoting. I would then be able to fix the rest by hand. My regex didn't cut it, because only variables not already in a string must be quoted.

Sample input:

echo "Removing $a ${b} $(c $(c)) `d $d` ${10} $@ now"
rm -rf $a ${b} $(c $(c)) `d $d` ${10} $@

Sample output:

echo "Removing $a $b $(c "$(c)") `d "$d"` ${10} $@ now"
rm -rf "$a" "$b" "$(c "$(c)")" "$(d "$d")" "${10}" "$@"

It doesn't have to fix all the above, and it doesn't even have to be flawless (though that would be really nice), but it has to be right more often than not to be useful.


Here is my naïve regex that didn't cut it:

s:([^"])\$\{([_A-Za-z0-9]+)\}([^"]|$):\1"\$\2"\3:g

It transforms ${identifier} to "$identifier", except when immediately preceded or followed by a quote, but fails to detect if we are deeper within the string.

like image 756
user2394284 Avatar asked Dec 12 '16 15:12

user2394284


People also ask

What does [- Z $1 mean in bash?

$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script. Follow this answer to receive notifications.

How do you parameterize a shell script?

A bash shell script have parameters. These parameters start from $1 to $9. When we pass arguments into the command line interface, a positional parameter is assigned to these arguments through the shell. The first argument is assigned as $1, second argument is assigned as $2 and so on...

What is #$ in bash?

#$ does "nothing", as # is starting comment and everything behind it on the same line is ignored (with the notable exception of the "shebang"). $# prints the number of arguments passed to a shell script (like $* prints all arguments).


2 Answers

WPomier beat me to it, but I did my own as well (because I wanted to):
https://github.com/anordal/shellharden

It acts as a syntax highlighter, until you give it the --transform option.

like image 180
user2394284 Avatar answered Nov 03 '22 00:11

user2394284


This is not an existent tool, but a little program in C, that it can help you as a base to get what you want.

You can see it here.

Example:

$ cat script.sh
echo "Removing $a ${b} $(c $(c)) `d $d` ${10} $@ now"
rm -rf $a ${b} $(c $(c)) `d $d` ${10} $@

$ checkshellvar < script.sh
echo "Removing $a ${b} $(c $(c)) `d $d` ${10} $@ now"
rm -rf "$a" "${b}" "$(c "$(c)")" "$(d "$d")" "${10}" "$@"

Disclaimer: The program achieves your sample output, but I did it in my coffee break, so don't expect too much ;-)

Note: Despite this program, I totally belieave that the quotes in shell scripting has a meaning, and their absence or the use of single or double quotes is perfectly valid depending on circumstances.

like image 36
Wilfredo Pomier Avatar answered Nov 02 '22 22:11

Wilfredo Pomier