Home > Net >  Passing parameters to find in bash script
Passing parameters to find in bash script

Time:03-28

I use this bash command often

find ~ -type f -name \*.smt -exec grep something {} /dev/null \;

so I am trying to turn it into a simple bash script that I would invoke like this

findgrep ~ something --mtime -12 --name \*.smt

Thanks to this answer I managed to make it work like this:

if ! options=$(getopt -o abc: -l name:,blong,mtime: -- "$@")
then
    exit 1
fi

eval "set -- $options"

while [ $# -gt 0 ]

do
    case $1 in
    -t|--mtime) mtime=${2}   ; shift;;
    -n|--name|--iname) name="$2" ; shift;;

    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
    (*) break;;
    esac
    shift
done

if [ $# -eq 2 ]
then
    dir="$1"
    str="$2"
elif [ $# -eq 1 ]
then
    dir="."
    str="$1"
else
    echo "Need a search string"
    exit
fi

echo "find $dir -type f -mtime $mtime -name $name -exec grep -iln \"$str\" {} /dev/null \;"
echo "find $dir -type f -mtime $mtime -name $name -exec grep -iln \"$str\" {} /dev/null \;" | bash

but the last line - echo'ing a command into bash - seems outright barbaric, but it works.

Is there a better way to do that? somehow trying to execute the find command directly gives no output, while running the one echo'ed out in bash works ok.

CodePudding user response:

ame $name -e

It's still not quoted. Check your script with shellcheck.

find "$dir" -type f -mtype "$mtime" -name "$name" -exec grep -iln "$str" {} ';'

You might want to take a few steps back and do some research about quoting and expansions in shel, find and glob. find program expects literal glob pattern, and unquoted variable expansions undergo filename expansion, changing *.smt into the list of words representing filenames, while find wants the pattern not the result of expansions.

I can throw: man find, man 7 glob, https://www.gnu.org/software/bash/manual/html_node/Quoting.html https://mywiki.wooledge.org/BashFAQ/050 https://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion

Before you start deciding how to pass variable number of arguments to find, I encourage to research Bash arrays. I would do:

#!/bin/bash

fatal() {
  echo "$0: ERROR: $*" >&2
  exit 1
}

args=$(getopt -o abc: -l name:,iname:,mtime: -- "$@") || exit 1
eval "set -- $args"
findargs=()  # bash array
while (($#)); do
    case $1 in
    -t|--mtime) findargs =(-mtime "$2"); shift; ;;
    -n|--name) findargs =(-name "$2"); shift; ;;
     --iname) findargs =(-iname "$2"); shift; ;;
    --) shift; break; ;;
    -*) fatal "unrecognized option $1"; ;;
    *) break; ;;
    esac
    shift
done

if (($# == 2)); then
    dir="$1"
    str="$2"
elif (($# == 1)); then
    dir="."
    str="$1"
else
    fatal "Need a search string"
fi

set -x
find "$dir" -type f "${findargs[@]}" -exec grep -iln "$str" /dev/null {}  
  •  Tags:  
  • bash
  • Related