2
dpkg -S /usr/share/doc/tasksel-data  # fine  
dpkg -S  usr/share/doc/tasksel-data  # fine  
dpkg -S     /share/doc/tasksel-data  # not found  
dpkg -S      share/doc/tasksel-data  # fine  
dpkg -S        are/doc/tasksel       # fine  

Why on Earth does the third line above fail? Note that line one starts with a slash(/), so that seems unlikely to be the problem.

Ray Andrews
  • 2,347

1 Answers1

5

This is not documented as far as I can tell but a leading / makes dpkg treat the argument as a path and not a pattern. In other words, if you tell it to search for something that starts with /, it assumes it should look for a file in one of the installed packages with that exact path.

You can confirm it easily enough with

$ dpkg -S nonmatching
dpkg-query: no path found matching pattern *nonmatching*
$ dpkg -S /nonmatching
dpkg-query: no path found matching pattern /nonmatching

Note that in the first case, with no /, the error shows that it searched for *nomatching*, while with the / it searched for the exact path /nonmatching. For example, it also fails to find /doc despite the existence of directories like /usr/share/doc:

$ dpkg -S /doc
dpkg-query: no path found matching pattern /doc

While I can't find any mention of this in the man page, I did confirm by checking the source. The following lines are from the searchfiles function defined in querycmd.c (dpkg 1.17.13)

if (!strchr("*[?/",*thisarg)) {
  varbuf_reset(&vb);
  varbuf_add_char(&vb, '*');
  varbuf_add_str(&vb, thisarg);
  varbuf_add_char(&vb, '*');
  varbuf_end_str(&vb);
  thisarg= vb.buf;
}   

That will add * around the argument passed unless that argument begins with a /. So, that causes dpkg-query to treat anything starting with / as an absolute path and anything that doesn't as a pattern to be matched.

terdon
  • 242,166
  • That could not be make more clear. Personally I think it should stick to 'matching pattern' searches, as the 'exact path' seems pointless, especially when '*' is implied at the end of the string anyway. – Ray Andrews Oct 11 '14 at 15:21
  • @rayandrews it's not. Anything that starts with a / is treated as a specific string to search for, not a pattern. Anything else has * added to the start and end. This is not implied, it is done explicitly in the lines I show and only for strings that don't start with one of those characters. This is actually very useful, for example, dpkg -S /bin/bash will tell me which package installed the specific executable found at /bin/bash while dpkg -S bash will return all matches. I can easily imagine situations where I want one or the other. – terdon Oct 11 '14 at 15:24
  • Ok, I see your point. You know, if this was only documented properly there would be no problem :( – Ray Andrews Oct 12 '14 at 14:28