I have written a small bash script to find if a directory named anaconda
or miniconda
in my user $HOME
. But it does not find the miniconda2
directory in my home.
How could I fix this?
if [ -d "$HOME"/"(ana|mini)conda[0-9]?" ]; then
echo "miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
P.S: If I have [ -d "$HOME"/miniconda2 ]; then
, then it finds the miniconda2 directory so I think error lies in the part "(ana|mini)conda[0-9]?"
I want the script to be general. For me, it's miniconda2 but for some other user it might be anaconda2, miniconda3 and so on.
This is a surprisingly tricky thing to do nicely.
Fundamentally,
-d
will only test a single argument - even if you could match filenames using a regular expression.One way would be to flip the problem around, and test directories for a regex match instead of testing the regex match for directories. In other words, loop over all the directories in
$HOME
using a simple shell glob, and test each against your regex, breaking on a match, finally testing whether theBASH_REMATCH
array is non-empty:An alternate way would be to use an extended shell glob in place of the regex, and capture any glob matches in an array. Then test if the array is non-empty:
The trailing
/
ensures that only directories are matched; thenullglob
prevents the shell from returning the unmatched string in the case of zero matches.To make either recursive, set the
globstar
shell option (shopt -s globstar
) and then respectively:-(regex version):
for d in "$HOME"/**/; do
(extended glob version):
dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )
Indeed, as already mentioned, this is tricky. My approach is the following:
find
and its regex capabilities to find the directories in question.find
print anx
for each found directoryx
es in a stringThus:
Explanation:
find $HOME -maxdepth 1
finds everything below$HOME
but restricts the search to one level (that is: it doesn't recurse into subdirectories).-type d
restricts the search to onlyd
irectories-regextype egrep
tellsfind
what type of regular expression we deal with. This is needed because things like[0-9]?
and(…|…)
are somewhat special andfind
doesn't recognize them by default.-regex "$HOME/(ana|mini)conda[0-9]?"
is the actual regular expression we want to lookout for-printf 'x'
just prints anx
for every thing that satisfies the previous conditions.You can loop over a list of directory names you want to test and act on it if one of them exists:
This solution obviously doesn’t allow for the full regex power, but shell globbing and brace expansion is equal at least in the case you showed. The loop exits as soon as one directory exists and unsets the previously set variable
a
. In the subsequentecho
line, the parameter expansion${a+not }
expands to nothing ifa
is set (= no dir found) and “not ” else.Possible work around is searching miniconda and anaconda separately as shown below
But if someone has suggestions, I'd like to know why we cannot pass a regex when searching for directories.