How to pass '*' wildcard to path parameter of find command via a variable in script?
Solution 1:
The exact same command should work fine in a script:
#!/usr/bin/env bash
find te*/my\ files/ -print
If you need to have it as a variable, it gets a bit more complex:
#!/usr/bin/env bash
search='te*/my\ files/'
eval find "$search" -print
WARNING:
Using eval
like that is not safe and can result in executing arbitrary and possibly harmful code if your file names can contain certain characters. See bash FAQ 48 for details.
It's better to pass the path as an argument:
#!/usr/bin/env bash
find "$@" -name "file*"
Another approach is to avoid find
altogether and use bash's extended globbing features and globs:
#!/usr/bin/env bash
shopt -s globstar
for file in te*/my\ files/**; do echo "$file"; done
The globstar
bash option lets you use **
to match recursively:
globstar
If set, the pattern ** used in a pathname expansion con‐
text will match all files and zero or more directories
and subdirectories. If the pattern is followed by a /,
only directories and subdirectories match.
To make it act 100% like find and include dotfiles (hidden files), use
#!/usr/bin/env bash
shopt -s globstar
shopt -s dotglob
for file in te*/my\ files/**; do echo "$file"; done
You can even echo
them directly without the loop:
echo te*/my\ files/**
Solution 2:
How about arrays?
$ tree Desktop/ Documents/
Desktop/
└── my folder
└── more
└── file
Documents/
└── my folder
├── folder
└── more
5 directories, 1 file
$ SEARCH=(D*/my\ folder)
$ find "${SEARCH[@]}"
Desktop/my folder
Desktop/my folder/more
Desktop/my folder/more/file
Documents/my folder
Documents/my folder/more
Documents/my folder/folder
(*)
expands into an array of whatever matches the wildcard. And "${SEARCH[@]}"
expands into all the elements in the array ([@]
), with each individually quoted.
Belatedly, I realise find itself should be capable of this. Something like:
find . -path 'D*/my folder/more/'
Solution 3:
It's a little dated now but, if that can help anybody with this question, using RE's collating symbol [[.space.]]
without quoting $SEARCH
variable within find command line arguments, is working as long as there's no special characters into the expanded path-names in place of the asterisk.
set -x
mkdir -p te{flon,nnis,rrine}/my\ files/more
SEARCH=te*/my[[.space.]]files/more
find $SEARCH
give the following results:
+ mkdir -p 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more'
+ SEARCH='te*/my[[.space.]]files/more'
+ find 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more'
teflon/my files/more
tennis/my files/more
terrine/my files/more
To prevent globing unwanted chars, One can replace the asterisk (*
) by any collating elements (characters):
set -x
mkdir -p -- te{,-,_}{flon,nnis,rrine}/my\ files/more
SEARCH=te[[:alnum:][.space.][.hyphen.][.underscore.]]*/my[[.space.]]files/more
find $SEARCH
giving the following results:
+ mkdir -p -- 'teflon/my files/more' 'tennis/my files/more' 'terrine/my files/more' \
'te-flon/my files/more' 'te-nnis/my files/more' 'te-rrine/my files/more' \
'te_flon/my files/more' 'te_nnis/my files/more' 'te_rrine/my files/more'
+ SEARCH='te[[:alnum:][.space.][.hyphen.][.underscore.]]*/my[[.space.]]files/more'
+ find 'te-flon/my files/more' 'te_flon/my files/more' 'teflon/my files/more' \
'te-nnis/my files/more' 'te_nnis/my files/more' 'tennis/my files/more' \
'te-rrine/my files/more' 'te_rrine/my files/more' 'terrine/my files/more'
te-flon/my files/more
te_flon/my files/more
teflon/my files/more
te-nnis/my files/more
te_nnis/my files/more
tennis/my files/more
te-rrine/my files/more
te_rrine/my files/more
terrine/my files/more
Note that to shorten the line,
[.hyphen.]
can be replaced by either [.-.]
or -
and
[.underscore.]
can be replaced by either [._.]
or _
.
Truncating lines with backslashes (\
) added by myself for readability purpose.