Reputation: 148
I encounter below strange problem in my shell script.
When i execute like below it doesn't work:
excom='/Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\*'
findcom=$(find /Development/temp_try ! \( -path $excom \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
Where as if i execute like below, it works fine:
findcom=$(find /Development/temp_try ! \( -path /Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\* \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
First one output is:
/Development/temp_try/f1
/Development/temp_try/f2
/Development/temp_try/f3
/Development/temp_try/f4
/Development/temp_try/f5
/Development/temp_try/f6
/Development/temp_try/f7
/Development/temp_try/f8
/Development/temp_try/try10
/Development/temp_try/log_test
/Development/temp_try/try10v
/Development/temp_try/try10v1
/Development/temp_try/try10j
/Development/temp_try/try10j1
/Development/temp_try/testing1/f1
/Development/temp_try/testing1/f2
/Development/temp_try/testing1/f3
/Development/temp_try/testing/test1/f1
/Development/temp_try/testing/test1/f2
/Development/temp_try/testing/test1/f3
/Development/temp_try/testing/test1/f4
/Development/temp_try/testing/test1/f5
/Development/temp_try/testing/test1/f6
/Development/temp_try/testing/test1/f7
/Development/temp_try/testing/test1/f8
/Development/temp_try/testing/f1
/Development/temp_try/testing/f2
/Development/temp_try/testing/f3
/Development/temp_try/testing/f4
/Development/temp_try/testing/f5
/Development/temp_try/testing/f6
/Development/temp_try/testing/f7
/Development/temp_try/testing/f8
/Development/temp_try/try10j1_working
/Development/temp_try/try11
/Development/temp_try/try11_original
/Development/temp_try/try8
where as the second one output is:
/Development/temp_try/f1
/Development/temp_try/f2
/Development/temp_try/f3
/Development/temp_try/f4
/Development/temp_try/f5
/Development/temp_try/f6
/Development/temp_try/f7
/Development/temp_try/f8
/Development/temp_try/try10
/Development/temp_try/log_test
/Development/temp_try/try10v
/Development/temp_try/try10v1
/Development/temp_try/try10j
/Development/temp_try/try10j1
/Development/temp_try/try10j1_working
/Development/temp_try/try11
/Development/temp_try/try11_original
/Development/temp_try/try8
Second one perfectly excludes the directories where as first doesn't. I have no clue how they both differ....
Thanks for Answers and comments, Now i understand the issue, could solve the problem.
#!/usr/bin/ksh
filepath="/Development/temp_try"
searchstring="corp.abc.com"
while read exfile
do
lasc=${exfile##${exfile%%?}}
if [ "$lasc" = "/" ]; then
exfile="$exfile*"
fi
if [ "$excom" = "" ]; then
excom="$exfile"
else
#excom="$excom -o -path '$exfile'"
set -A excom "$excom" '-o' '-path' "$exfile"
fi
done <input4
echo "The exclude command is ${excom[@]}"
findcom=$(find $filepath ! \( -path "${excom[@]}" \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF $searchstring {} \;)
for filename in $findcom
do
echo $filename
done
My input4 file contains below lines:
/Development/temp_try/testing/
/Development/temp_try/testing1/
Upvotes: 0
Views: 94
Reputation: 241721
Inside a single-quoted string, \
has no special significance. So the result of
excom='/Development/temp_try/testing/\* -o -path /Development/temp_try/testing1/\*'
is that the value of excom
will include two backslash characters.
Backslash characters are not special in filename expansions, so when the value of $excom
is filename-expanded and wordsplit (because its expansion is not quoted), the backslash characters continue to be ordinary characters. So the expansion of
find /Development/temp_try ! \( -path $excom \) ...
has the literal words:
find
/Development/temp_try
!
(
-path
/Development/temp_try/testing/\*
-o
-path
/Development/temp_try/testing1/\*
Nothing matches the pattern /Development/temp_try/testing/\*
because your filenames do not include backslashes.
Had you left out the backslashes when you defined excom:
excom='/Development/temp_try/testing/* -o -path /Development/temp_try/testing1/*'
then the filename patterns would have been expanded in the invocation of find. In this case, find /Development/temp_try ! \( -path $excom \) ...
would expand to:
find
/Development/temp_try
!
(
-path
/Development/temp_try/testing/f1
/Development/temp_try/testing/f2
/Development/temp_try/testing/f3
...
which is also not what you want, since the -path
predicate needs to be followed by exactly one pattern, not by a list of filenames.
Consequently, you need to pass the value of excom
as a list of quoted words. The only simple way to do that in bash is to use an array, because you can expand an array into a list of quoted array values:
excom=("/Development/temp_try/testing/*"
-o -path "/Development/temp_try/testing1/*")
findcom=$(find /Development/temp_try ! \( -path "${excom[@]}" \) \
-type f \( ! -name "*.HPSEPFQDN.*" ! -name "*.HPSEPIPCHG."* \) \
-exec grep -lF "corp.abc.com" {} \;)
(That definition of findcom
, which is not quoted, assumes that no filename produced by the -exec grep
command will have whitespace or a pattern metacharacter in its name. In general, that's not a safe assumption.)
Upvotes: 3
Reputation: 785146
Don't store command line (fully or partially) in simple variables as it creates many issues at the time of variable expansion in shell.
Better to store in shell arrays like this
excom=('/Development/temp_try/testing/*' -o -path '/Development/temp_try/testing1/*')
findcom=$(find /Development/temp_try ! \( -path "${excom[@]}" \) -type f \( ! -name \*.HPSEPFQDN.\* ! -name \*.HPSEPIPCHG.\* \) -exec grep -lF "corp.abc.com" {} \;)
Upvotes: 3