0

I am writing a script that prompts for user inputs and then runs a find command.

What I have works, but it feels like I have a lot of duplicated code due to the if / else structure. Is it possible to have inline if statement?

So, instead of this kind of thing:

if [[ $depth_boolean == y ]] || [[ $depth_boolean == yes ]]
    then
        if [[ $symlink_boolean == y ]] || [[ $symlink_boolean == yes ]]
        then
            find -L $location -maxdepth $depth -readable -iname "$query" -$find_type $find_type_option -$find_action
        else
            find $location -maxdepth $depth -readable -iname "$query" -$find_type $find_type_option -$find_action
        fi
    else
        if [[ $symlink_boolean == y ]] || [[ $symlink_boolean == yes ]]
        then
            find -L $location -readable -iname "$query" -$find_type $find_type_option -$find_action
        else
            find $location -readable -iname "$query" -$find_type $find_type_option -$find_action
        fi
    fi

Is it possible to do something like this?

find if [ $symlink_boolean == y ]; then echo "-L";
   fi $location if [ $symlink_boolean == y ]; then 
   echo "-maxdepth $depth"; fi -readable -iname "$query" 
   -$find_type $find_type_option -$find_action

The above doesn't work, but wondering if it is possible?

ilkkachu
  • 138,973
kerrin
  • 103

1 Answers1

2

You can deal with the symlink with a simple variable:

symlink_flag=
if [[ $symlink_boolean == y ]]; then
    symlink_flag=-L
fi
find $symlink_flag "$location" -maxdepth "$depth" -readable ...

Note that $symlink_flag is unquoted here, so if empty, it disappears. The value it has doesn't contain any wildcards or default IFS characters, so not quoting it doesn't cause any harm. The other variables should be quoted, since e.g. the location might well contain whitespace.

For the depth part, your best bet is to build the command line in an array:

arguments=()
if [[ $symlink_boolean == y ]]; then
    arguments+=(-L)
fi
arguments+=("$location")
if [[ $depth_boolean == y ]]; then
    arguments+=(-maxdepth "$depth")
fi
find "${arguments[@]}" -readable -iname ...

You can put the nonchanging options on the find command line as above, or just unconditionally append them to the array and just run find "${arguments[@]}".

See also:


Technically, you can also do what you propose with command substitution:

find $(if [[ $symlink_boolean == y ]]; then printf %s -L; fi) "$location"
    $(if [[ $depth_boolean == y ]]; then echo -maxdepth $maxdepth; fi) ...

Though in general this is not optimal, the only way to produce multiple words from the command substitution is to have them space-separated and then split, but that again doesn't work well if there are words within that should contain whitespace. -maxdepth N should work, though.


As a side note, you can condense the conditions a bit by using e.g. [[ $symlink_boolean == [Yy]* ]]. It would check if the variable starts with a Y or a y. (If you don't mind stuff like YEAAHHH also being truthy values.) Use the regex match [[ $symlink_boolean =~ ^(y|yes)$ ]] or case $symlink_boolean in y|yes) echo "true";; esac to just allow the two values.

ilkkachu
  • 138,973
  • Thank you so much for all your help. I've changed it up to build the command line into an array first as you suggested. Thanks for the info about conditions too. – kerrin Nov 21 '18 at 08:40