Reputation: 1130
I need to build up an argument list for find
using values only known at run time. I'm trying to use an array to do so.
Below is a simplified version which uses hard coded values. When I echo out the command it appears to be correct (and when I run it manually it does what I'd expect). When it enters the for-loop it appears to be running find
(because I can see the same errors about Permission denied
for directories owned by other users as when I run manually). But inside the for-loop, it doesn't echo out any of the .txt
files that a manual run finds.
What did I do wrong?
#!/bin/bash
args=(/tmp -iname \"*.txt\")
#args+=(-o -iname \"*.jpg\")
echo command will be: find ${args[@]}
for f in $( find ${args[@]} ); do
echo found $f
done
The accepted answer below correctly identified the issue. But if I add an additional -iname
clause, my script "ignores" all but the last as detailed here:
#!/bin/bash
args=($1)
args+=(-maxdepth $2)
args+=(-iname "*$3")
args+=(-o -iname "*$4")
echo command will be: find "${args[@]}"
find "${args[@]}" -print 2>/dev/null | while read -r f; do
echo found "$f"
done
For example, when called with /home/me 2 .jpg .png
this correctly echoes that the command will be find /home/me -maxdepth 2 -iname *.jpg -o -iname *.png
but then my script only echoes the .png
files that it finds.
Upvotes: 1
Views: 73
Reputation: 669
Bash4 can expand globs recursively with shopt -s globstar
.
Just use array=(/tmp/**/*.txt)
to get all the elements.
Upvotes: 1
Reputation: 780724
You shouldn't escape the quotes. That will make them literal, so it will try to find files whose names actually begin and end with doublequotes.
args=(/tmp -iname "*.txt")
Then you need to put quotes around ${args[@]}
to tell the shell that it should requote them when expanding the array:
find "(" "${args[@]}" ")" -print | while read -r f
do
echo found "$f"
done
Upvotes: 3