I find it strange that when I use the *
wildcard , ls
sometimes takes it literally. Here's the actual case: I have the following folder structure:
This is the output of ls
00 02 04 06 08 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 99 Codes X12
01 03 05 07 09 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 98 ALL_RAW Implemented_NN_Model.h5
Each of the numbered folders (00 to 99) contains the following files:
00_Binarized_Cutoff_0.99_.tif 00_dot_img_model.png 00_Final_Loc.tif 00_Raw_Prediction.tif Implemented_NN_Model.h5
I want to extract all the *_Final_Loc.tif
files from these folders.
Hence I tried this:
ls -R *Final*tif
, and this: ls *Final*tif
.
I get the same output in both cases:
ls: cannot access '*Final*tif': No such file or directory
I am just curious to know why ls
takes the *
literally, and what is the correct way?
A side information, I was able to do this task, but when I used this:
ls [0-9][0-9]/*Final*tif
i.e.,
for file in `ls [0-9][0-9]/*Final*tif` ; do cp ${file} ../ALL_Final_Loc/ ; done
And this is strange too, since I don't find a logical explanation for why it should work here.
CodePudding user response:
Glob expansion is done by the shell. When you run ls *Final*tif
bash will find files which match the pattern *Final*tif
and paste their names to the command. As there are no files with names like that in the current directory, the expansion fails and ls
now receives a literal *Final*tif
as parameter which obviously doesn't exist and produces the error
ls: cannot access '*Final*tif': No such file or directory
Same to ls -R *Final*tif
. To find files like that use find
:
find -name "*Final*tif"
CodePudding user response:
For Filename Expansion, if there are no files that match the pattern, the default behaviour is that the pattern then remains in the command as a literal string. (The shell options nullglob
and failglob
can control this behaviour)
The reason why the pattern matches no files is because there are no directory separators in it. You want
echo */*Final*tif
or
find . -name '*Final*tif' -ls
CodePudding user response:
You have to specify the directory as well like so:
ls */*Final*tif
Unfortunately, ls -R
doesn't work with wildcards in a particularly useful way so for a case where there are multiple directory levels you could use find
, like so:
find . -name '*Final*tif'