Home > front end >  Bash 'ls' does not accept * wildcard
Bash 'ls' does not accept * wildcard

Time:04-02

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'

  • Related