For an assignment, I'm supposed to write a bash script that can act as a very basic find, but without actually using the find command. For example, if I put in this input:

my_find ~/homedir/ -name 'test*' -name '*.o' -type f

I need it to search ~/homedir/ for anything matching the name test* with the wildcard character, then AND that and search within those results for anything matching a *.o name, and finally (although possibly redundant), search for only files. Finally, it will list all the results.

As of now, I've made a variable that stores the directory path (dirpath=$1). I then use shift to get rid of the first argument, and then do this (note that -type isn't implemented yet):

while (($#)); do
    if [[ $1 == "-name" ]]; then
        # process the name here?
        shift 2 # get rid of -name "name"
    fi
done

I'm kind of wondering how I can structure or even do this. I have a partially done function that will recurse through the directory path, but I'm not sure how / where I can process the argument passed in. Here is the recursive function to look through each directory.

recurse_path () {
    for i in "$@"; do
        # process and store matching file names in the array?
        if [[ -d "${i}" ]]; then
            cd "${i}"
            recurse_path *
        fi
    done
}

So how can I search for my matching file names and store the results in an array while using this function? Also, is this the right way to do this, or is there a potentially easier way to update the results I get as each command is looked at? I'm brand new to bash scripting so I would appreciate any advice.

  • 1
    If there is some reason to explore new bicycle if your function act in same way and with same arguments syntax like find? – Costas Feb 25 '15 at 9:45
  • @Costas I have to complete it as an assignment :( Otherwise I would most definitely just use find – Alex Feb 25 '15 at 9:50
  • not sure what exactly you are lack of . what is your skill level ? are you familiar with common programming languages like pascal or c ? if so , all you need is a man 1 bash . – 把友情留在无盐 Feb 25 '15 at 10:57
  • @soubunmei I am familiar with c and am just learning bash scripting. I'm supposed to implement my own find method with just a few basic parameters. – Alex Feb 25 '15 at 11:02
  • 1
    You need to declare i as a local variable, for obvious reasons. Also after the cd and recurse_path you need to go back to the previous directory. Store that previous directory in another local variable. – wurtel Feb 25 '15 at 11:08

let me try point something basic .

1.

if we already can travel through directory trees , next thing is to search in the current visiting directory . this depends on what style of pattern syntax we want to support . regex is a whole different thing . maybe we are satisfied with the shell built-in pattern grammar . then this will do .

for i in * ; do for p in <patterns> ; do
        if [[ $i == $p ]]
        ...
        fi
done ; done

2.

for parsing the commandline , bash has the getopts builtin , refer to the manual .

3.

for arrays , refer to the manual .

  • 1
    getopts can be used to parse single letter options, not find predicates. – Stéphane Chazelas Feb 25 '15 at 11:26

A dirty solution would look like:

boolRememberNext=0
rememberString=""

for arg in $*; do
   if [ ${boolRememberNext} -eq 1 ]; then
      rememberString="${rememberString} ${arg}"
   fi
   if [ "${arg}" = "-name" ]; then
      boolRememberNext=1
   else
      boolRememberNext=0
   fi
done

echo ${rememberString} | while read filemask; do
   unquotedFile=$(echo "$filemask" | tr -d "'")
   ls -R1 ~/homedir/ | grep ":" | cut -d: -f1 | while read dir; do
      ls ${dir}/unquotedFile
   done
done

Why is it dirty?

  • A lot of loops, the filesystem is accessed many times
  • Incorrect commmandline syntax is ignored
  • directory and file names may not have an : inside
  • the unquoting of the var with tr will not handle * combinations
    I do not want to use eval for this

What could be done to improve the solution?

You can store intermediate results in local var's, improve handling of special chars and check the syntax.

You can also perform a ls ~/homedir/* and add an asterisk to the searchpath until no files are found. Parse all files through some filter (awk?). Check the files you find, that they are files, not directories.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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