LinuxQuestions.org
View the Most Wanted LQ Wiki articles.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 03-05-2011, 08:43 AM   #1
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Rep: Reputation: 3
confused about usage of quotes and wildcards in linux


Hello everybody
I am struggling to learn command line in Linux and have noticed a confusing (at least for me ) behaviour of wildcards and quotting
E.g :
Code:
ioannis@ioannis-laptop:~$ locate *te* | wc -l
29
ioannis@ioannis-laptop:~$ locate '*te*' | wc -l
30096
ioannis@ioannis-laptop:~$ locate te | wc -l
30096
when quotting *te* , you get the equivalent of te which makes sense since * is not expressed but why does *te* gives different results?

And :

Code:
ioannis@ioannis-laptop:~$ locate *arca* | wc -l
38
ioannis@ioannis-laptop:~$ locate *arca* | wc -l
38
ioannis@ioannis-laptop:~$ locate '*arca*'| wc -l
38
here, just giving a different argument you get idenctical results

Another case
Code:
ioannis@ioannis-laptop:~/Music$ find -name '*th*' | wc -l
15
ioannis@ioannis-laptop:~/Music$ find -name th | wc -l
0
ioannis@ioannis-laptop:~/Music$ find -name *th* | wc -l
find: paths must precede expression: Beautiful South Perfect10.flv
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
0
here, you get a different behaviour ( th is not treated s '*th*') and presumably in *th* , * is considered as "all"
So, is the behaviour of quotting and/or wildcards different depending on the command or am I missing something else ?
Thanks in advance
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 03-05-2011, 09:44 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by joham34 View Post
Hello everybody
I am struggling to learn command line in Linux and have noticed a confusing (at least for me ) behaviour of wildcards and quotting
E.g :
Code:
ioannis@ioannis-laptop:~$ locate *te* | wc -l
29
ioannis@ioannis-laptop:~$ locate '*te*' | wc -l
30096
ioannis@ioannis-laptop:~$ locate te | wc -l
30096
when quotting *te* , you get the equivalent of te which makes sense since * is not expressed but why does *te* gives different results?

And :

Code:
ioannis@ioannis-laptop:~$ locate *arca* | wc -l
38
ioannis@ioannis-laptop:~$ locate *arca* | wc -l
38
ioannis@ioannis-laptop:~$ locate '*arca*'| wc -l
38
here, just giving a different argument you get idenctical results

Another case
Code:
ioannis@ioannis-laptop:~/Music$ find -name '*th*' | wc -l
15
ioannis@ioannis-laptop:~/Music$ find -name th | wc -l
0
ioannis@ioannis-laptop:~/Music$ find -name *th* | wc -l
find: paths must precede expression: Beautiful South Perfect10.flv
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
0
here, you get a different behaviour ( th is not treated s '*th*') and presumably in *th* , * is considered as "all"
So, is the behaviour of quotting and/or wildcards different depending on the command or am I missing something else ?
Thanks in advance
The command you are using may have its own wildcard expansion, so it may itself expand '*te*' you are giving it on command line.

Try the following program:

Code:
#!/usr/bin/perl

use strict;
use warnings;

warn "command line arguments - one per line:\n";
my $arg_number = 0;
foreach my $arg(@ARGV)
  {
  warn "[$arg_number] $arg\n";
  $arg_number++;
  }
to see how your shell expands wildcards. I.e. save the code, as, say, 'args.pl' file, give the file executable permission and try it with, say,

Code:
./args.pl *te*
.

If you want the test program to print to stdout and not stderr as it does, replces 'warn' with 'print'.

Last edited by Sergei Steshenko; 03-05-2011 at 10:33 AM.
 
Old 03-05-2011, 10:14 AM   #3
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,562

Rep: Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939
As you are using Ubuntu, you are more than likely running dash as a shell. This is quite similar to bash but with some different tweaks (none of which I think are affecting you here).
Sergei is quite right in saying that different applications / commands will have their own idiosyncrasies, but in this case I would say in all the situations where you have not quoted
the string it is expanding to what it finds in the directory you are running in prior executing the command.

Your first 2 examples are a good demonstration of this:
Code:
ioannis@ioannis-laptop:~$ locate *te* | wc -l
ioannis@ioannis-laptop:~$ locate *arca* | wc -l
When you quote or remove the wildcards then locate only has the information at hand to use, however, when using the unquoted wildcard version it first expands the string to whatever it finds locally.
Hence if in the directory you have a file called:
Code:
after
arcane
Now locate will only look for things that have these words / strings appear inside a file or directory name.

Once quoted though, this now effectively passes the wildcards to locate and it performs its' own version of expansion as part of its' lookup.
 
1 members found this post helpful.
Old 03-05-2011, 10:18 AM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948
There are two levels of processing going on. First the shell processes the command line, then it passes it to the program, which does whatever it's designed to do.

In the locate example without quoting, the shell first tries to match files in the current directory and builds anything it matches into a list of filenames. This list is then passed to locate. Only if there are no matches does it pass the string on literally.

Try running echo locate *te* and see what you get.

Now lets look at what the locate man page says about how it processes the strings it gets:
Code:
If a pattern is a plain string  it contains no metacharacters  locate displays
all file names in the database that contain that string anywhere.  If a pattern
does contain metacharacters, locate only displays file names that match the
pattern exactly.
So in example one, you appear to have approximately 29 files in your directory that contain the text "te", which are having their names passed to locate. locate then searches for those file names as plain text strings, and not coincidentally comes up with a list of the files in that directory (and perhaps a few identically named files in other locations).

The same thing is happening with find. The unprotected shell globbing is finding one match in the current directory for *th*, which when passed onto find is producing a syntax error due to the spaces in it.

So the lesson learned is that you should nearly always quote strings when they contain anything other than plain text, and sometimes even then.
 
2 members found this post helpful.
Old 03-05-2011, 11:09 AM   #5
Telengard
Member
 
Registered: Apr 2007
Location: USA
Distribution: Kubuntu 8.04
Posts: 579
Blog Entries: 8

Rep: Reputation: 147Reputation: 147
Your shell (Bash, Dash, Sh, whatever) is expanding the unquoted wildcard character (*) before locate ever sees it.

A classic demonstration may be helpful. Try this on your own system and see what happens.

Code:
$ mkdir junk
$ cd junk
$ touch one two three four five
$ echo *e*
five one three
Here the shell expands the pattern before the echo command even begins to run. echo never sees the pattern, just arguments "five one three".

locate is capable of expanding patterns, but if you don't quote your pattern then the shell will eat it first. The same happens with find --name

Edit:
A bit of related advice ... if you ever use regular expression from the command line, enclose the entire regex inside single quotes. Leaving a regex exposed to the shell is asking for all kinds of confusion.

Last edited by Telengard; 03-05-2011 at 12:09 PM.
 
1 members found this post helpful.
Old 03-05-2011, 03:03 PM   #6
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
@grail
"say in all the situations where you have not quoted
the string it is expanding to what it finds in the directory you are running in prior executing the command."

I tested locate *te* and it gives me several results some of them in my home dir (where I run the command) and others outside it. A small sample is :

Code:
/home/ioannis/Desktop/home_backup/ioannis/Templates
/home/ioannis/GNUstep/Library
/usr/share/app-install/icons/_usr_lib_GNUstep_Applications_AClock.app_Resources_AClock.tiff
/usr/share/app-install/icons/_usr_lib_GNUstep_Applications_BioCocoa.app_Resources_biococoa.tiff
So it shouldnt be the case that unquoted *te* is searched only in the dir I am running it



When you quote or remove the wildcards then locate only has the information at hand to use, however, when using the unquoted wildcard version it first expands the string to whatever it finds locally.
Hence if in the directory you have a file called:
Code:
after
arcane
Now locate will only look for things that have these words / strings appear inside a file or directory name.




It was very important for me to realize that different applications / commands will have their own idiosyncrasies and I should memorize some things instead of trying to solve all problems with logic as well as to understand that there are the 2 levels of processing as you describe

Also , I think I have bash :
Code:
ioannis@ioannis-laptop:~$ which bash
/bin/bash

Last edited by joham34; 03-06-2011 at 01:01 PM.
 
Old 03-05-2011, 03:14 PM   #7
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
Smile

Quote:
Originally Posted by David the H. View Post
There are two levels of processing going on. First the shell processes the command line, then it passes it to the program, which does whatever it's designed to do.

In the locate example without quoting, the shell first tries to match files in the current directory and builds anything it matches into a list of filenames. This list is then passed to locate. Only if there are no matches does it pass the string on literally.

Try running echo locate *te* and see what you get.

Now lets look at what the locate man page says about how it processes the strings it gets:
Code:
If a pattern is a plain string  it contains no metacharacters  locate displays
all file names in the database that contain that string anywhere.  If a pattern
does contain metacharacters, locate only displays file names that match the
pattern exactly.
So in example one, you appear to have approximately 29 files in your directory that contain the text "te", which are having their names passed to locate. locate then searches for those file names as plain text strings, and not coincidentally comes up with a list of the files in that directory (and perhaps a few identically named files in other locations).

The same thing is happening with find. The unprotected shell globbing is finding one match in the current directory for *th*, which when passed onto find is producing a syntax error due to the spaces in it.

So the lesson learned is that you should nearly always quote strings when they contain anything other than plain text, and sometimes even then.
Well , thanks, definitely i should quote and the message is taken. \
But ..
Code:
ioannis@ioannis-laptop:~$ locate *te* | more -2
/etc/GNUstep
/etc/GNUstep/GNUstep.conf
And in none of the rest 27 results is there any *te*
I have very little experience and please correct me if I am wrong but I start understanding that it doesnt make sense to try to understand how command line responds when you dont follow the rules
 
Old 03-05-2011, 03:29 PM   #8
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
Quote:
Originally Posted by Telengard View Post
Your shell (Bash, Dash, Sh, whatever) is expanding the unquoted wildcard character (*) before locate ever sees it.

A classic demonstration may be helpful. Try this on your own system and see what happens.

Code:
$ mkdir junk
$ cd junk
$ touch one two three four five
$ echo *e*
five one three
Here the shell expands the pattern before the echo command even begins to run. echo never sees the pattern, just arguments "five one three".

locate is capable of expanding patterns, but if you don't quote your pattern then the shell will eat it first. The same happens with find --name

Edit:
A bit of related advice ... if you ever use regular expression from the command line, enclose the entire regex inside single quotes. Leaving a regex exposed to the shell is asking for all kinds of confusion.

Thanks for your reply, I think the last part of your post is the most usefull In the
And, I got "five one three" too.
I wonder though to what could the * in *te* be expanded by the shell and only 29 results (all of them containing te though) but finally I understand the answer is not important
 
Old 03-05-2011, 05:43 PM   #9
Telengard
Member
 
Registered: Apr 2007
Location: USA
Distribution: Kubuntu 8.04
Posts: 579
Blog Entries: 8

Rep: Reputation: 147Reputation: 147
Exclamation Yes, it really is important!

Quote:
Originally Posted by joham34 View Post
I wonder though to what could the * in *te* be expanded by the shell and only 29 results (all of them containing te though) but finally I understand the answer is not important
It really is important, if you want to learn how to get best possible use of your shell. Try these examples.

Code:
$ mkdir foo
$ cd foo
$ echo *mandb*
*mandb*
  • Bash expands *mandb* into the set of all file names which match the pattern. (I think this is what is meant by globbing.)
  • Because no matches are found, *mandb* is passed unchanged to echo.
  • echo receives the argument *mandb* and prints it to stdout.

Quote:
Originally Posted by Bash Reference Manual, 3.5.8 Filename Expansion
Bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern. If no matching file names are found, and the shell option nullglob is disabled, the word is left unchanged.
Bash Reference Manual, 3.5.8 Filename Expansion

Code:
$ touch fake-mandb-file
$ echo *mandb*
fake-mandb-file
  • Bash expands *mandb* into the set of all file names which match the pattern. The file fake-mandb-file is the one and only match.
  • The string fake-mandb-file is passed to echo.
  • echo receives the argument fake-mandb-file and prints it to stdout.

The locate command without any options searches its entire database (the one maintained by updatedb). It is not restricted to your current directory.

Code:
$ pwd
/home/me/foo
$ ls
fake-mandb-file
$ sudo updatedb
[sudo] password for me:
$ locate mandb
/home/me/foo/fake-mandb-file
/usr/bin/mandb
/usr/lib/man-db/mandb
/usr/share/man/de/man8/mandb.8.gz
/usr/share/man/es/man8/mandb.8.gz
/usr/share/man/fr/man8/mandb.8.gz
/usr/share/man/it/man8/mandb.8.gz
/usr/share/man/ja/man8/mandb.8.gz
/usr/share/man/man8/mandb.8.gz
  • When invoked without options, locate returns results from all directories indexed by its database.
  • The string mandb is interpreted by locate as if it were *mandb*.

Quote:
Originally Posted by man locate
If any PATTERN contains no globbing characters, locate behaves as if the pattern were *PATTERN*.
locate(1)

Hope you're still reading, because here comes the most important part.

Code:
$ locate *mandb*
/home/me/foo/fake-mandb-file
In the previous example we used pattern mandb, and locate found several files from the /usr/ hierarchy. Why didn't it find them this time?
  • Bash expands *mandb* into the set of all file names which match the pattern.
  • The file fake-mandb-file is the one and only match.
  • The argument fake-mandb-file is passed to locate.
  • locate searches its database for file names matching fake-mandb-file.
  • /home/me/foo/fake-mandb-file is the one and only match, representing all of the directories in your filesystem indexed by the locate database.

I hope that now you can see why locate *te* might not return the same results as locate '*te*'. It is crucial to understand when Bash is eating your unquoted wildcard patterns and expanding them into unexpected strings of gibberish.

Code:
$ locate '*mandb*'
/home/me/foo/fake-mandb-file
/usr/bin/mandb
/usr/lib/man-db/mandb
/usr/share/man/de/man8/mandb.8.gz
/usr/share/man/es/man8/mandb.8.gz
/usr/share/man/fr/man8/mandb.8.gz
/usr/share/man/it/man8/mandb.8.gz
/usr/share/man/ja/man8/mandb.8.gz
/usr/share/man/man8/mandb.8.gz
That's more like it!
 
1 members found this post helpful.
Old 03-06-2011, 11:14 AM   #10
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
Quote:
Originally Posted by Telengard View Post
It really is important, if you want to learn how to get best possible use of your shell. Try these examples.

Code:
$ mkdir foo
$ cd foo
$ echo *mandb*
*mandb*
  • Bash expands *mandb* into the set of all file names which match the pattern. (I think this is what is meant by globbing.)
  • Because no matches are found, *mandb* is passed unchanged to echo.
  • echo receives the argument *mandb* and prints it to stdout.


Bash Reference Manual, 3.5.8 Filename Expansion

Code:
$ touch fake-mandb-file
$ echo *mandb*
fake-mandb-file
  • Bash expands *mandb* into the set of all file names which match the pattern. The file fake-mandb-file is the one and only match.
  • The string fake-mandb-file is passed to echo.
  • echo receives the argument fake-mandb-file and prints it to stdout.

The locate command without any options searches its entire database (the one maintained by updatedb). It is not restricted to your current directory.

Code:
$ pwd
/home/me/foo
$ ls
fake-mandb-file
$ sudo updatedb
[sudo] password for me:
$ locate mandb
/home/me/foo/fake-mandb-file
/usr/bin/mandb
/usr/lib/man-db/mandb
/usr/share/man/de/man8/mandb.8.gz
/usr/share/man/es/man8/mandb.8.gz
/usr/share/man/fr/man8/mandb.8.gz
/usr/share/man/it/man8/mandb.8.gz
/usr/share/man/ja/man8/mandb.8.gz
/usr/share/man/man8/mandb.8.gz
  • When invoked without options, locate returns results from all directories indexed by its database.
  • The string mandb is interpreted by locate as if it were *mandb*.


locate(1)

Hope you're still reading, because here comes the most important part.

Code:
$ locate *mandb*
/home/me/foo/fake-mandb-file
In the previous example we used pattern mandb, and locate found several files from the /usr/ hierarchy. Why didn't it find them this time?
  • Bash expands *mandb* into the set of all file names which match the pattern.
  • The file fake-mandb-file is the one and only match.
  • The argument fake-mandb-file is passed to locate.
  • locate searches its database for file names matching fake-mandb-file.
  • /home/me/foo/fake-mandb-file is the one and only match, representing all of the directories in your filesystem indexed by the locate database.

I hope that now you can see why locate *te* might not return the same results as locate '*te*'. It is crucial to understand when Bash is eating your unquoted wildcard patterns and expanding them into unexpected strings of gibberish.

Code:
$ locate '*mandb*'
/home/me/foo/fake-mandb-file
/usr/bin/mandb
/usr/lib/man-db/mandb
/usr/share/man/de/man8/mandb.8.gz
/usr/share/man/es/man8/mandb.8.gz
/usr/share/man/fr/man8/mandb.8.gz
/usr/share/man/it/man8/mandb.8.gz
/usr/share/man/ja/man8/mandb.8.gz
/usr/share/man/man8/mandb.8.gz
That's more like it!
Thank you for your comprehensive reply
I think it makes sense but just to make sure I understood this
When giving the argument te , the bash searches for a file named exactly te, doesnt find any and it passes te unchanged to the command locate which in turn regards it as *te* because of the way locate works, searches its databese (created by updatedb) for *te* and finds a big number of matches since it looks for files containing te in their names
When given as *te* , bash performs the pathname expansion, finds a few matches only, passes these expanded matches to the command locate which of course returns the same number of matches.
So, it is clear why *te* gives different results than te .
My only question is where does the bash search to find files
And also :
I understood that the quoted argument is not usefull with locate when looking in a specific directory

Last edited by joham34; 03-06-2011 at 01:34 PM.
 
Old 03-06-2011, 02:00 PM   #11
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948
Quote:
Originally Posted by joham34 View Post
When giving the argument te , the bash searches for a file named exactly te, doesnt find any and it passes te unchanged to the command locate...
This part is incorrect. Since the command line does not contain any special wildcard characters, NO globbing/file matching is attempted at all, and the string te is simply passed straight to locate as-is. Not that it really matters though, as the same simple text string is passed whether there's a match or not.

The rest of your paragraph is correct.

Quote:
My only question is where does the bash search to find files
Globbing is attempted in the current directory only, unless the pattern includes a relative or absolute path. locate ../*te* would attempt to glob in the directory above the one you're in and locate /home/user/*te* would likewise attempt to glob the user's home directory. Globbing also ignores hidden dotfiles by default, but this can be changed with the dotglob shell option.
 
1 members found this post helpful.
Old 03-06-2011, 03:20 PM   #12
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
Quote:
Originally Posted by David the H. View Post
This part is incorrect. Since the command line does not contain any special wildcard characters, NO globbing/file matching is attempted at all, and the string te is simply passed straight to locate as-is. Not that it really matters though, as the same simple text string is passed whether there's a match or not.

The rest of your paragraph is correct.



Globbing is attempted in the current directory only, unless the pattern includes a relative or absolute path. locate ../*te* would attempt to glob in the directory above the one you're in and locate /home/user/*te* would likewise attempt to glob the user's home directory. Globbing also ignores hidden dotfiles by default, but this can be changed with the dotglob shell option.
Thanks you for your correction about the fact that bash doesnt search for te . So , it is now clear that bash intervenes only to process wildcards , otherwise just passes the argument to locate

But, something peculiar happens here :
Now , when giving

Code:
ioannis@ioannis-laptop:~$ locate *te* | wc -l
31812
As you see now I get 31812 results instead of 29 giving the same command while being in the same dir (home) and not having changed anything ! (to be absolutely sure I did copy-paste the command from my own post
In my comment nr 7 here, while I was getting only 29 results you see 2 of them ( there were more), not belonging to my home dir (in which I was while giving the command), so it appears that bash did not search only locally
Any idea?
 
Old 03-06-2011, 03:22 PM   #13
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
Quote:
Originally Posted by David the H. View Post
This part is incorrect. Since the command line does not contain any special wildcard characters, NO globbing/file matching is attempted at all, and the string te is simply passed straight to locate as-is. Not that it really matters though, as the same simple text string is passed whether there's a match or not.

The rest of your paragraph is correct.



Globbing is attempted in the current directory only, unless the pattern includes a relative or absolute path. locate ../*te* would attempt to glob in the directory above the one you're in and locate /home/user/*te* would likewise attempt to glob the user's home directory. Globbing also ignores hidden dotfiles by default, but this can be changed with the dotglob shell option.
Thanks you for your correction about the fact that bash doesnt search for te . So , it is now clear that bash intervenes only to process wildcards , otherwise just passes the argument to locate

But, something peculiar happens here :
Now , when giving

Code:
ioannis@ioannis-laptop:~$ locate *te* | wc -l
31812
As you see now I get 31812 results instead of 29 giving the same command while being in the same dir (home) and not having changed anything ! (to be absolutely sure I did copy-paste the command from my own post)
In my comment nr 7 here, while I was getting only 29 results you see 2 of them ( there were more), not belonging to my home dir (in which I was while giving the command), so it appears that bash did not search only locally
Any idea?
 
Old 03-06-2011, 04:34 PM   #14
Telengard
Member
 
Registered: Apr 2007
Location: USA
Distribution: Kubuntu 8.04
Posts: 579
Blog Entries: 8

Rep: Reputation: 147Reputation: 147
Thumbs up David the H. has it right



Quote:
Originally Posted by joham34 View Post
When giving the argument te , the bash searches for a file named exactly te, doesnt find any and it passes te unchanged to the command
No. Bash only performs expansions on unquoted pattern matching characters.

Quote:
Originally Posted by Bash Reference Manual, 3.5.8 Filename Expansion
Bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern. If no matching file names are found, and the shell option nullglob is disabled, the word is left unchanged.
Bash Reference Manual, 3.5.8 Filename Expansion

Code:
$ locate te 
/bin/date
/bin/mktemp
/bin/tempfile
/boot/System.map-2.6.24-23-generic
/boot/System.map-2.6.24-24-generic
/boot/System.map-2.6.24-25-generic
/boot/System.map-2.6.24-26-generic
/boot/System.map-2.6.24-27-generic
/boot/System.map-2.6.24-28-generic
/boot/memtest86+.bin
... (goes on for too many lines to include here) ...
  • Bash passes the string te unchanged to the locate command because there are no unquoted pattern matching characters in te.
  • locate receives the argument te and internally transforms it to *te*.
  • locate returns the set of all file names in its database which match the pattern *te*.

Quote:
Originally Posted by man locate
If any PATTERN contains no globbing characters, locate behaves as if the pattern were *PATTERN*.
locate(1)

Quote:
When given as *te* , bash performs the pathname expansion, finds a few matches only, passes these expanded matches to the command locate which of course returns the same number of matches.
Try and prove it for yourself.

Code:
~$ mkdir foo
~$ cd foo
~/foo$ touch fake-te-file one two three
~/foo$ ls
fake-te-file  one  three  two
~/foo$ sudo updatedb
~/foo$ locate *te*
/home/me/foo/fake-te-file
~/foo$ echo *te*
fake-te-file
  • Bash expands *te* into the set of all file names which match the pattern *te*. Only fake-te-file matches.
  • Bash passes fake-te-file to locate.
  • locate accepts the argument fake-te-file and internally tranforms it to the pattern *fake-te-file*.
  • locate searches its database for all file names which match the pattern *fake-te-file*.
  • locate returns the one and only result, /home/me/foo/fake-te-file

Quote:
where does the bash search to find files
Bash compares strings with unquoted pattern matching characters against the names of files in the current working directory. As David the H. correctly pointed out, Bash also obeys any relative paths you specify like ./subdir/ or ../otherdir/ when matching the pattern.

Code:
~/foo$ mkdir bar
~/foo$ touch bar/one bar/two bar/three
~/foo$ ls bar
one  three  two
~/foo$ echo bar/*e*
bar/one bar/three


Quote:
Originally Posted by joham34 View Post
Code:
ioannis@ioannis-laptop:~$ locate *te* | wc -l
31812
As you see now I get 31812 results instead of 29 giving the same command while being in the same dir (home) and not having changed anything !
I can't really say because I don't know your system. My best guess is that no files in your current working directory match the pattern, so locate receives the argument *te*.

Quote:
Originally Posted by Bash Reference Manual, 3.5.8 Filename Expansion
If no matching file names are found, and the shell option nullglob is disabled, the word is left unchanged.
Bash Reference Manual, 3.5.8 Filename Expansion

I suppose it is also conceivable that your system is configured somewhat differently with regards to locate and/or shell options. I can't even guess what those differences might be. In such a case you will have to review the appropriate documentation and configuration files with great intensity to discover the cause. I very much doubt this is the case though.
 
1 members found this post helpful.
Old 03-07-2011, 04:12 AM   #15
joham34
Member
 
Registered: Oct 2009
Location: Greece
Distribution: ubuntu 14.04
Posts: 75

Original Poster
Rep: Reputation: 3
Question

Thanks again for your detailed reply
I have made clear in my mind that bash intervenes only to do the globbing and that if no globbing is required, it passes the arguments to locate.


Bash compares strings with unquoted pattern matching characters against the names of files in the current working directory. As David the H. correctly pointed out, Bash also obeys any relative paths you specify like ./subdir/ or ../otherdir/ when matching the pattern.

Code:
~/foo$ mkdir bar
~/foo$ touch bar/one bar/two bar/three
~/foo$ ls bar
one  three  two
~/foo$ echo bar/*e*
bar/one bar/three


I presume this is what should happen and indeed, when giving e.g
Code:
ioannis@ioannis-laptop:~/Music$ locate *th* | wc -l
17
I get the expected result

I can't really say because I don't know your system. My best guess is that no files in your current working directory match the pattern, so locate receives the argument *te*.

No , it cant be the case because I didnt change anything .Something really strange ins going on :

Code:
ioannis@ioannis-laptop:~$ mkdir kate
ioannis@ioannis-laptop:~$ sudo updatedb
ioannis@ioannis-laptop:~$ locate *te* | wc -l
391
ioannis@ioannis-laptop:~$ rm -r kate
ioannis@ioannis-laptop:~$ sudo updatedb
ioannis@ioannis-laptop:~$ locate *te* | wc -l
29
29 again ! hurahh !

And only about the half belong to my home dir :

Code:
ioannis@ioannis-laptop:~$ locate *te* | tail -2
/usr/share/librarian/Templates/C
/usr/share/librarian/Templates/C/scrollkeeper_cl.xml

I suppose it is also conceivable that your system is configured somewhat differently with regards to locate and/or shell options. I can't even guess what those differences might be. In such a case you will have to review the appropriate documentation and configuration files with great intensity to discover the cause. I very much doubt this is the case though.[/QUOTE]

I have a clean installation of Ubuntu 10.10 64 bit and have touched nothing related to configurations of bash .

I suspect that a bug is a possibility here
 
  


Reply

Tags
expansion, pattern, quoting, shell, wildcard


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Yet Another Bash Quotes Within Quotes Issue tboyer Linux - Software 17 11-03-2012 11:17 AM
Problems with quotes and double quotes Andruha Slackware 6 01-02-2010 04:44 PM
Using single quotes vs double quotes in PHP strings vharishankar Programming 6 07-11-2005 11:41 AM
how to determine cpu usage, memory usage, I/O usage by a particular user logged on li rags2k Programming 4 08-21-2004 04:45 AM
In BASH shell, what is the difference in usage between single and double quotes? davidas Linux - Newbie 2 04-05-2004 03:00 AM


All times are GMT -5. The time now is 02:21 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration