1

I newly learned how to search multiple file names with find like:

find . \( -iname "*.srt" -o -iname "*.mp4" \)

But in some cases I had to use so many filters like this and that simple command line became so long:

find . \( -iname "*.srt" -o ......... \)

Can I create a variable and add this all filters in it, then use it again in find command? Thank you!

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
  • 2
    Does this answer your question? [variable \`-name\` primary to \`find\`](https://unix.stackexchange.com/questions/456863/variable-name-primary-to-find) – steeldriver Dec 30 '19 at 21:57
  • Storing commands (or parts of commands) in variables is problematic (see [BashFAQ #50](http://mywiki.wooledge.org/BashFAQ/050)). If you're running `find` repeatedly with the same list of patterns, a function would be a much better choice. – Gordon Davisson Dec 31 '19 at 21:07

3 Answers3

3

With the GNU implementation of find, there is another way to search multiple file names:

rgx='.*\.srt\|.*\.mp4'
find . -iregex "$rgx"

The \| is the logical regex OR (in the default regexps types of GNU find which are the emacs ones). A naked . means any char. and a dot is \..

You could define a $rgx_compr and a $rgx_media, and then combine it:

find . -iregex "$rgx_compr" -o -iregex "$rgx_media"

I left out the parens here.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
3

Since you're using a shell that supports array variables (i.e. bash) you can create an array variable and use that directly.

Constant expression

find . \( -iname "*.srt" -o -iname "*.mp4" \) ...

Variable expression

opts=(-iname "*.srt" -o -iname "*.mp4")
find \( "${opts[@]}" \) ...

Or

opts=( '(' -iname "*.srt" -o -iname "*.mp4" ')' )
find "${opts[@]}" ...

Notice that the array variable expansion itself must be double-quoted ("${opts[@]}") even though it contains one or more items. If the array contains no items it will expand to nothing (not the empty string, "").

roaima
  • 107,089
  • 14
  • 139
  • 261
-3

Yes, it is possible. With the method I show below, take care of the usage of quotations, wildcards, etc. Nonetheless, here is one solution in BASH:

opt="-iname '*.srt' -o -iname '*.mp4'"
find . \( $(eval echo ${opt}) \)

While it is not possible to simply call the ${opt} variable in the find command, we can work around it by using the eval command in $(eval echo ${opt}) line.

Jason K Lai
  • 534
  • 2
  • 8
  • 2
    This answer has problems. `eval` is full of traps for the unwary, and I don't recommend using it unless you have a deep understanding of shell parsing. In this case, it'll have trouble if there are matching files directly in the current directory. (And there are some other, weirder problems here.) – Gordon Davisson Dec 31 '19 at 21:04