When the bash
shell can't find a file that matches a given globbing pattern, it leaves the pattern unexpanded. This leads to, in your find
command, that ls
gets the unexpanded pattern *.e*
as its argument. The ls
utility does not do expansions of filename globbing patterns by itself but relies on the shell to have done that already.
This is most likely your issue with your last find
command that only seems to be able to work correctly from your home directory, probably because your home directory contains files matching the pattern (.bashrc
, for example, matches .b*
). When the patterns don't match anything in the current directory, the pattern will be handed to ls
as it is, and since ls
does not expand globbing patterns by itself, it would fail to list any files.
In short, you can't call ls
directly with -execdir
or -exec
and give it a filename globbing pattern.
You additionally say that you want to list the files matching *.e*
for "further processing". I would urge not to do that, and instead to do that processing in the actual find
command itself. The reason for this is given in the question/answer "Why is looping over find's output bad practice?".
So, instead of what you're currently doing, consider
find . -type f -name md.tpr -exec bash -O nullglob -O dotglob -c '
for pathname do
dirpath=${pathname%/md.tpr}
for e in "$dirpath"/*.e*; do
# process "$e" here!
done
done' bash {} +
This is assuming that md.tpr
is a regular file that should be found. The find
command would find the pathnames of all these md.tpr
files and feed them in batches to an inline bash
script. The bash
script is short:
for pathname do
dirpath=${pathname%/md.tpr}
for e in "$dirpath"/*.e*; do
# process "$e" here!
done
done
This simply takes the given arguments, extracts the directory component of each (by removing the /md.tpr
suffix string, which we know is there, from the pathname) and loops over the files matching *.e*
in each directory (with $e
holding the pathname of each matched file in turn).
The in-line script is run with the nullglob
and dotglob
options set, so that the *.e*
pattern would be removed completely if it doesn't match, and so that the pattern would match hidden names.
A bit more info about using -exec
with find
can be found in "Understanding the -exec option of `find`".
Since you've tagged this question with bash, this is how to do the same thing in a plain bash
loop (this requires bash
release 4 or later):
shopt -s globstar nullglob dotglob
for pathname in ./**/md.tpr; do
dirpath=${pathname%/md.tpr}
for e in "$dirpath"/*.e*; do
# process "$e" here!
done
done
Apart from there not being any checks for whether the matched md.tpr
files are regular files or not, this should look very similar to the in-line script called by find
above. The globstar
shell option in bash
enables the **
glob, which matches "recursively" down into subdirectories.
I would expect this to be slightly slower than using find
, but it may be a more convenient way of writing the code.
find
tols
seems a bit redundant, and I hope you were careful if you tried to parse the output.ls
. The point was to find some files that live in the same file as another file (and then process them further).