0

Does anyone know why using two *'s in a grep command will not return anything. My original command is as follows:

find | grep 0000\:00\:*.0/usb1/authorized_default

In this example, I am attempting to return a file that I do not know the PCI folder name. This command works perfectly and as expected(taking the * as a wildcard) and figuring out that usb1 is in the '1a' folder.

Why does grep not return any results if I place another wildcard in the command to replace 'usb1' with 'usb*'? My end goal is to return all of the authorized_default files which I realize can be done other ways and probably more efficiently. My question then becomes not how can I do this but why does grep not return a result when I put another '*' symbol into the equation?

find | grep 0000\:00\:*.0/usb*/authorized_default

Thanks in advance for your time and responses.

James Lane
  • 101
  • 1

2 Answers2

6

grep uses regular expressions, not shell globs.

The regex 0000:00:*.0/usb1/authorized_default matches the string 0000:00 + zero or more colons + any character + 0/usb1/authorized_default.

If you swap the * and the ., it will match any string that contains 0000:00 followed by 0/usb1/authorized_default. (.* matches any number (*) of any character (.).)

Similarly, usb*/ will match us/, usb/, usbbb/ etc, but not usb1.


Actually, there's also the issue that the unquoted * in the argument to grep is taken as a glob character by the shell, before grep even sees it. So, if there are files that would match 0000\:00\:*.0/usb*/authorized_default as a glob pattern, that would affect the string that goes to grep. Multiple matches would go as multiple arguments, and grep would take the ones after the first as filenames.

Put quotes around any regular expressions on the command line to prevent that.


In any case, you don't even need the grep here, as @Kusalananda says. The -name option to find can be used to match filenames against a glob pattern. At least some find implementations also have the -regex option to match file names against regular expressions.


There are also a number of variants of regular expressions, see: Why does my regular expression work in X but not in Y?

ilkkachu
  • 138,973
2

As ilkkachu already pointed out, grep uses basic regular expressions, which means that :* matches zero or more :, and b* matches zero or more b.


Do not grep the output of find, instead use find to look for your file. In the general case, filenames may contain newlines, which would make grepping not work. Using find to directly filter the pathnames that you want to see is also more efficient, and safer.

find . -type f -name 'authorized_default'

If you have to do matching on other parts of the pathname:

find . -type f -path '*0000:00:*.0/usb*/authorized_default'

-path works like -name but matches a filename globbing pattern against the whole path rather than just against the filename part of the pathname (a * may match across one or several /).

Related:

Kusalananda
  • 333,661