3

From locate man page:

If --regex is not specified, PATTERNs can contain globbing characters. If any PATTERN contains no globbing characters, locate behaves as if the pattern were *PATTERN*.

Now, see the output from these commands:

test@ubuntu:~$ ls
Desktop  Documents  Downloads  Firefox_wallpaper.png  Music  Pictures  Public  Templates  Videos
test@ubuntu:~$ 
test@ubuntu:~$ 
test@ubuntu:~$ locate '/bin/bash*'
test@ubuntu:~$ 
test@ubuntu:~$ 
test@ubuntu:~$ locate /bin/bash*
/snap/core18/1880/bin/bash
/snap/core18/1880/usr/bin/bashbug
/snap/core18/1944/bin/bash
/snap/core18/1944/usr/bin/bashbug
/usr/bin/bash
/usr/bin/bashbug

If you see my present working directory have no file/directory whose full path name begins with /bin/bash. Hence, we should not be receiving any output from locate /bin/bash*. Why ? According to globbing feature of shell , since I have no such file/directory in my current working directory, hence, the * will be not be expanded and passed as it is. Hence, it should be equivalent to using locate '/bin/bash*'(which is our 2nd command run above). Since, this does not receive any output, hence this locate /bin/bash* should not also give output ?

Number945
  • 167
  • 8

2 Answers2

5

If you see my present working directory have no file/directory whose full path name begins with /bin/bash. Hence, we should not be receiving any output from locate /bin/bash*

No, that's not how shell globbing works - /bin/bash* matches including the path, so given that it finds a match (i.e. /bin/bash), that's the argument that locate will receive. You can verify this by running the command with the shell's -x debug parameter set:

$ set -x
$ 
$ locate /bin/bash*
+ locate /bin/bash
/bin/bash
/snap/core/10577/bin/bash
/snap/core/10577/usr/bin/bashbug
/snap/core/10583/bin/bash
/snap/core/10583/usr/bin/bashbug
/snap/core18/1932/bin/bash
/snap/core18/1932/usr/bin/bashbug
/snap/core18/1944/bin/bash
/snap/core18/1944/usr/bin/bashbug
/usr/bin/bashbug

Since the (expanded) pattern contains no globbing characters, it's equivalent to */bin/bash*.

The more interesting question is why it doesn't locate /bin/bash itself, given that the shell apparently does - I think that's because /bin is symlinked to /usr/bin on newer versions of Ubuntu - and updatedb doesn't record symlinks.

steeldriver
  • 131,985
  • 21
  • 239
  • 326
  • So, just to confirm my understanding, if I had given `locate *c` , it would have searched for all paths in system which have `c` at end like say for example `/home/test/ab.c` and then searched for `*/home/test/ab.c*` in the database ? If yes, then [this answer](https://askubuntu.com/a/829752/489387) is wrong , is not it ? It says, it will search in current working directory. – Number945 Jan 25 '21 at 20:51
  • 1
    `/bin/bash*` matches against files in the `/bin` directory because of the absolute path; `*c` matches against files in the current directory (equivalent to `./*c`) – steeldriver Jan 25 '21 at 20:58
  • I was busy writing my answer, didn't see this one until I posted mine. Nice explanation and informative. +1 – Raffa Jan 25 '21 at 20:59
  • @Number945 no. `*c` doesn't have any slashes in it, so it only expands to the names of files in the *current directory* ending with `c`. – hobbs Jan 26 '21 at 05:36
2

Firstly

The locate command matches the provided pattern to its database. This is how it works. This means two things:

  • Whatever you are trying to find has to be in its database and it is not enough that it exists in your file system. The database should update regularly but sometimes it takes time and the command to do this manually is sudo updatedb

  • Considering the above on how locate works, it does not make any difference from which directory you run the locate command as locate itself does not search or even see the current directory. All it knows is its database.

Secondly

When you pass the unprotected (unquoted) pattern containing globbing characters to locate, the pattern is not passed to locate. What is passed to locate in this case is the expanded version done by the shell itself and that could contain all sorts of thing that afterwords will be treated as multiple patterns by locate and it will compare all that to its database and print output accordingly. You have no reliable way to control what is passed to locate in this case and it is up to the shell to decide.

The proper way to prevent the shell from interfering and expanding patterns with globbing characters in them is to protect or escape these characters. In short use quotation marks either single or double around the pattern, like so:

locate '/bin/bash*'
Raffa
  • 24,905
  • 3
  • 35
  • 79