I've been learning stuff about bash
rapidly in the last several years, including better and faster ways of accomplishing common tasks. Here are some of my favorites.
Random n lines of a file
Antipattern
ls | shuf | head -n1
Improvement
ls | shuf -n1
I learned this week that the venerable shuf
utility comes with functionality to select the top "n" lines of the file produced by the last pipe step! This saves an invocation of head
and a good bit of typing.
Filter by lines with grep, then by column with awk
Antipattern
ls -lt | grep -E '^d' | awk '{print $2}'
Improvement
ls -lt | awk '/^d/{print $2}'
I did this for years until someone sat me down and explained a bit more of awk
to me. If there was an award for "useless use of grep", it would go to this common shell pattern I see every day. If you're looking to filter lines by a regular expression, then filter down to a specific column, awk can take care of all of that for you. Everything inside the //
is an extended PCRE, so you don't have to pass any flags (like grep
) to get what you want.
Unnecessary loops
Antipattern
git ls-files | while read line; do rm "$line"; done
Improvement
git ls-files | xargs -L 1 rm
If you're only executing a single command against each element of a bash loop, you can quickly replace your use of the loop with an xargs
invocation. The -L 1
flag for xargs
allows you to process each line of input separately- exactly like a bash while loop. If you don't care about the serialization of the operations in this loop, you can parallelize it with xargs -P