0

The script which I have requires two inputs one is the filepath and the other being filename which is used to check the existence of a file using find command.

#!/bin/bash

Filepath=$1
Filename=$2

if [ -z "$Filepath" ] && [ -z "$Filename" ]
then
        echo "Requires Input"
elif [ ! -z "$Filepath" ] && [ ! -z "$Filename" ]
then
        Found=`find "$Filepath" -iname "$Filename"`
                if [ -z "$Found" ]
                then
                        echo "Not Found"
                else
                        echo $Found
                fi
fi

This works completely fine as expected. Later I had to add couple of more conditions to this script i.e. if we get only the filename as the input parameter the we have search that file in the entire file system as given below

find / -iname "$Filename"

And in case if only the filepath input parameter is passed to this script then it has to echo that file name parameter is also required or just has to come out.

  • What is the question you're attempting to ask? – John Sep 28 '16 at 15:01
  • Based on the input parameters I have to execute the condition. Basically I have two input parameters for my script and I need four condition to be made, 1. If both parameters are passed (filepath and filename) then it has to execute the find command with the both. 2.If both the parameters are not passed then prompt of echo asking for the input parameters. 3.If only filepath ($1) parameter is passed then it has to prompt asking for the filename. 4.If only filename ($2) parameter is passed to the script then it has to search the entire system i.e. "/" for that file. – ramp Sep 28 '16 at 15:17
0

I'd do:

#! /bin/sh -
pattern=${1?Please provide a file name}
shift

[ "$#" -gt 0 ] || set /

find "$@" -iname "$pattern" | grep '^' && exit

echo >&2 "Not found"
exit 1

That is, pass the name (note that find treats it as a (case insensitive because of -iname) pattern to match agains file names, not as an exact file name to find) as the first argument. Any other argument are directories or files to search in, and if none is given, search in /.

Rather than storing the output in a variable and display it at the end, use grep as a pass-through and that reports true if a file has been found.

Also, I'm outputting the "Not found" message on stderr instead of stdout, and reporting the failure to find the file in the exit status.

As noted by @ThomasN, there's the usual problem that you can't pass file/directory names reliably to find. If you want to search in a directory called -delete, calling that-script name -delete for instance would have disastrous effects. With BSDs find, that can be worked around by doing (before calling find):

for i do
  set -- "$@" -f "$i"
  shift
done

Portably (though note that -iname is not portable), you'd need to prepend ./ to relative paths that may be problematic like with:

for i do
  case $i in
    (. | ./* | /*) ;; # /foo, ./foo are not a problem
    (*) i=./$i
  esac
  set -- "$@" "$i"
  shift
done
find "$@"...

That does affect the output though (as in you'll see ./delete/name instead of -delete/name).

  • 1
    While this passes the requirements test, some input validation on $@ would be helpful to prevent garbage (or malice) from destroying data. E.g., (assuming the script is named finder_script.sh): ./finder_script.sh some_file /home/mydir/ -ok rm \{\} \; – Thomas N Sep 28 '16 at 16:00
  • @ThomasN, yes, that's an usual problem with find in that you can't pass it arbitrary file names reliably. BSD find has the -f option for that but it's not supported by GNU find yet, so we'd need to prepend ./ to all relative paths which would affect the output. – Stéphane Chazelas Sep 28 '16 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.