Conditional command execution within piped sequence of commands in bash

917 views Asked by At

Sorry for bumpy topic name (feel free to edit if you find more fitting title after looking at problem). Code sample equals 1000 words, so here we go:

if [ "$REGEX" != "" ]; then
        find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' |                                  
        grep -E $REGEX |
        awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' | 
        while read -r line; do mv -f $line; done 
else
        find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' |
        awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' |
        while read -r line; do mv -f $line; done
fi

What code does is not all that important, I'd just like to find more elegant way to either use "grep -E $REGEX" or not. I thought that conditdonal aliases could do the job just like I'm used to from shell usage, but they does not work inside scripts.

I could put in a condition, but I fear performance impact from multiple evaluations.

Any way to make the code "more elegant"?

3

There are 3 answers

1
ruakh On BEST ANSWER

One simple way is to use ^ (which always matches: it means "start-of-line", which every line has) if $REGEX is unset or blank:

find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' |
grep -E ${REGEX:-^} |
awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' |
while read -r line; do mv -f $line; done

For that matter, you can combine it into the original find:

find $TEST_DIR -type f -regextype posix-extended \
     -regex '^.*(status|stderr|stdout)-captured$' \
     -regex ".*${REGEX}.*" |
awk '{print(""$1" "$1)}' | sed 's/-captured$/-expected/' |
while read -r line; do mv -f $line; done

and for that matter, you can merge all of the rest of your script into find as well:

find $TEST_DIR -type f -regextype posix-extended \
     -regex '^.*(status|stderr|stdout)-captured$' \
     -regex ".*${REGEX}.*" \
     -exec bash -c 'file="{}" ; mv -f "$file" "${file%-captured}-expected"' \;
0
William Pursell On

A very simple solution is:

test -n "$REGEX" && cmd="grep -E $REGEX"
find ... | ${cmd-cat} | awk ...

If cmd is defined, it is used in the pipe. Otherwise, cat is used, performing a no-op. You can also do:

find ... |
if test -n "$REGEX"; then
  grep -E $REGEX
else
  cat
fi |
awk ...

with exactly the same effect.

0
ams On

Here's a slightly ugly, but general, solution.

find $TEST_DIR -type f -regextype posix-extended -regex '^.*(status|stderr|stdout)-captured$' \
 | if [ "$REGEX" != "" ]; then
        grep -E $REGEX; \
   else \
        cat; \
   fi \
 | awk '{print(""$1" "$1)}' \
 | sed 's/-captured$/-expected/' \
 | while read -r line; do mv -f $line; done