0

Expected Function: write a bash script showing all the regular files with filename ended with ".xml" or ".yml" and with path not begined with "./target/", i.e., exclude the "target" subdirectory.

Example File List: ./a/a1.xml; ./a/a2.txt; ./b/b1.yml; ./target/t.xml; Example Outout: ./a/a1.xml; ./b/b1.yml

I construct find options in a bash shell script like

#!/bin/bash
find_opts=( -type f -a ( -not -path "./target/*" ) -a ( -false -o -name "*.xml" -o -name "*.yml" ) )
find . $find_opts

But it does not output the expected result. Howver, when I tpye the full command string in bash terminal as follows:

[root@localhost]#find . \( -type f -a \( -not -path "./target/*" \) -a \( -false -o -name "*.xml" -o -name "*.yml" \) \)

it works. What is the problem about the above bash script ?

==============================================================

Someone gives this reference link : Expanding a bash array only gives the first element

It is about "bash array". But it seems that my problem is not about "bash array". Would anyone give any reasons?

Please see How to exclude a directory in find . command to known why I use parentheses whiches look like an array. Anyway, I try two others attempts:

#the first one
find_opts=( -type f -a ( -not -path "./target/*" ) -a ( -false -o -name "*.xml" -o -name "*.yml" ) )
#the second one
find_opts=\\( -type f -a \\( -not -path "./target/*" \\) -a \\( -false -o -name "*.xml" -o -name "*.yml" \\) \\)
#the third one
find_opts=\( -type f -a \( -not -path "./target/*" \) -a \( -false -o -name "*.xml" -o -name "*.yml" \) \)

The first one and the third one give the same output which is unexpeced result. The second one occures an error.

syntax error near unexpected token `('

The problem is still here.

==============================================================

Someone give one more reference:Why does shell ignore quoting characters in arguments passed to it through variables? It is about how to use bash array to pass arguments and the problem is solved by the following code:

#!/bin/bash
find_opts=(\( -type f -a \( -not -path './target/*' \) -a \( -false -o -name '*.xml' -o -name '*.yml' \) \))
find . "${find_opts[@]}"
Zongxiang Yi
  • 113
  • 1
  • 5
  • The immediate problem is that you are using the wrong syntax to refer to the array; see the duplicate. But furthermore, your conditions are artificially complex. They can be reduced to `find . -type f \( -not -path "./target/*" \) -name "*.[xy]ml"` – tripleee Apr 10 '22 at 10:12
  • @tripleee I think there is no array in my case.Can you point out which variable shoule be array ? – Zongxiang Yi Apr 10 '22 at 10:42
  • It's not a matter of belief. `find_opts=( ... )` creates an array with the values in `...`. Not using an array is broken for other reasons; I'm adding a separate duplicate about that. – tripleee Apr 10 '22 at 10:44
  • @tripleee It (`find_opts`) is not intended to be an array if you use `find` to do the same task. So I change my code. But the problem is still. Please see the edited OP. – Zongxiang Yi Apr 10 '22 at 10:47
  • `find_opts=\( -type ...` assigns the opening parenthesis to the string variable `find_opts` for the duration of the attempt to run `-type ...` as a command. Probably review [When to wrap quotes around a shell variable?](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable); but again, as the second duplicate points out, basically never attempt to use a string variable to store nontrivial command options. – tripleee Apr 10 '22 at 11:56
  • Tangentially, questions should remain strictly questions, but it doesn't matter much here, as [low-traffic duplicates typically get deleted after a while.](/help/roomba) – tripleee Apr 10 '22 at 11:59
  • There appears to be no compelling reason to use a variable for part of your command here anyway; probably the basic lesson here really is just "don't do that." – tripleee Apr 10 '22 at 12:00

0 Answers0