Try every option for a command and make anagrams out of the successful ones What I have: I am trying to find what words you can make out of Linux command options like ls -cat or ps -elf. To do that I am iterating through an array of 50 commands, trying to run each with flags -[a-z] and then making anagrams out of the successful options. It is working and here is what I have:

#!/bin/bash

# Pull in a list of common Linux commands
commandList=( $(
  curl 'http://www.thegeekstuff.com/2010/11/50-linux-commands/' 2&gt; /dev/null \
    | grep -o '&lt;h3&gt;\([0-9].*[a-z][a-z][a-z].*\)&lt;/h3&gt;' \
    | awk '{ print $(NF-2) }' \
    | sed -nr '/rm|wget|less|shutdown|&lt;h3&gt;/!p'
) );

# Pipe successful "$command -$option" pairs to 'an' to generate anagrams
for command in ${commandList[@]} ; do
    (for option in {a..z} ; do
        timeout -k 5 5 "$command" -"$option" &gt; /dev/null 2&gt;&amp;1;
            if (($? == 0)); then
                printf "$option" | tr -d '\n'
            else
                    :
            fi
    done) | xargs an -w -d saneWordlist -m 3 2&gt; /dev/null \
          | sed 's/^/\ '$command' -/' &gt;&gt; commandOptions.log
done    


Self Criticism:
I know it is unreliable to rely on exit codes that are not at all consistent and just hoping the devs used 0 to indicate success. I also know I abused sed and awk a lot. I also didn't try to write this in a very POSIX-y way.

What I want help on:
I am not too worried about the web scraping part, I know it is cheap and messy. But, how can I improve the core section where I misuse sed and awk so much? I know there cleaner ways to accomplish what I want, but can't think of anything.
Some of the commands in the web scraping part can be simplified.

Instead of awk '{ print $(NF-2) }', why not simply awk '{ print $2 }'?

Instead of sed -nr '/rm|wget|less|shutdown|&lt;h3&gt;/!p', it would be simpler and more portable to use grep -vE 'rm|wget|less|shutdown|&lt;h3&gt;'.

Using a Bash array is a bit overkill,
because the output of the pipeline is guaranteed to be one word per line,
no other white space.
So using a simple variable and word splitting should do the job, and simpler:

commandList=$(
  curl 'http://www.thegeekstuff.com/2010/11/50-linux-commands/' 2&gt; /dev/null \
    | grep -o '&lt;h3&gt;\([0-9].*[a-z][a-z][a-z].*\)&lt;/h3&gt;' \
    | awk '{ print $2 }' \
    | grep -vE 'rm|wget|less|shutdown|&lt;h3&gt;'
)

for command in $commandList; do




Many improvements are possible here:


timeout -k 5 5 "$command" -"$option" &gt; /dev/null 2&gt;&amp;1;
    if (($? == 0)); then
        printf "$option" | tr -d '\n'
    else
            :
    fi



In Bash, you can use &amp;&gt;/dev/null to redirect both stdout and stderr.

Since $option only contains a single letter and printf doesn't print a trailing newline like echo, the tr command there is pointless.
The double-quotes around $option are also unnecessary.
The empty else branch should be removed.

Instead of using a condition on $?, you could use the command itself directly:

if timeout -k 5 5 "$command" -$option &amp;&gt; /dev/null; then
    printf $option
fi




You could rewrite the final sed simpler using double-quotes:

sed "s/^/ $command -/" &gt;&gt; commandOptions.log


I also removed a pointless \ from in front of a space within the quoted expression.