bufferoverflow76
bufferoverflow76

Reputation: 797

wrapping bash find command

I want to write a simple bash script to wrap the default unix/linux find program in bash to find multiple files matched.

Here is my program named my_find_command:

#!/bin/bash

patt=""
first=true
for i in "$@"; do
  if [ "$first" = true ]; then
    patt="-name '$i'"
    first=false
  else
    patt="${patt} -o -name '$i'"
  fi
done

echo "$patt"
find . -type f \( ${patt} \)
echo 'done'

Assume I do have some files that the find command would be able to return some files.

But when I call my_find_command icon.png profile.png I got nothing.

What went wrong here?.

Upvotes: 2

Views: 414

Answers (1)

John1024
John1024

Reputation: 113864

Quotes within strings do not work the way you want them to. You are correct that ./my_find_command icon.png will not find icon.png. But, it will find 'icon.png'. For example:

$ ls
'icon.png'  my_find_command
$ ./my_find_command my_find_command icon.png 
-name 'my_find_command' -o -name 'icon.png'
./'icon.png'
done

The problem comes from trying to put multiple command arguments in a variable. For a full explanation of the ways that this goes wrong, see "I'm trying to put a command in a variable, but the complex cases always fail!". Instead, use an array:

#!/bin/bash    
patt=()
for i in "$@"; do
  if [ "${#patt}" -eq 0 ]; then
      patt=(-name "$i")
  else
      patt+=(-o -name "$i")
  fi
done

echo "${patt[@]}"
find . -type f \( "${patt[@]}" \)
echo 'done'

This now prints the correct files:

$ ls
'icon.png'  icon.png  my_find_command
$ ./my_find_command my_find_command icon.png 
-name my_find_command -o -name icon.png
./icon.png
./my_find_command
done

To demonstrate that wildcards work correctly:

$ ls
'icon.png'  icon.png  my_find_command

$ ./my_find_command my_find_command '*icon.png*'
-name my_find_command -o -name *icon.png*
./icon.png
./my_find_command
./'icon.png'
done

Upvotes: 3

Related Questions