5

I am trying to perform this:

locate pg_type.h | cat

But this command simply does nothing different than locate pg_type.h

What should I change ? I want to perform cat pg_type.h wherever pg_type.h may be.

  • 2
    You are running locate(1), and sending its output to the input of cat(1), which dutifully copies its input to its output. Nothing to see here, move along. – vonbrand Feb 26 '13 at 1:02
  • 1
    Also note that locate is not reliable for information about what is on your filesystem right now. – Wildcard Aug 22 '16 at 23:51
  • IIRC it is updated at each reboot of the system. I usually use it because it's really fast, and wonder everytime if it is a new file or not. – Stephane Rolland Aug 23 '16 at 7:21
12
locate -e0 '*/pg_type.h' | xargs -r0 cat

locate pg_type.h would find all the files with pg_type.h in their path (so for instance if there was a rpg_type.horn directory, you'd end up displaying all the files in there).

Without -0 the output of locate can't be post-processed because the files are separated by newline characters while newline is a perfectly valid character in a file name.

cat without arguments writes to stdout what it reads from stdin, so locate | cat would be the same as locate, cat would just pass the output of locate along. What you need is to pass the list of files as arguments to cat.

That's what xargs is typically for: convert a stream of data into a list of arguments. -r is to not call cat if there's no input. Without -0 (which like -r is not standard but found on many implementations, at least those where xargs is useful to anything), xargs would just look for words in its input to convert into arguments, where words are blank separated and where backslash, single and double quotes can be used to escape those separators, so typically not the format locate uses to display file names.

That's why we use the -0 option for both locate and xargs which uses the NUL character (which is the only character not allowed in a file path) to separate file names.

Also note that locate is not a standard command and there exist a great number of different implementations with different versions thereof and different options and behaviours. The code above applies at least to relatively recent versions of the GNU locate and mlocate implementations which are the most common on Linux based operating systems at least.

  • +1, and answer for all the good details. It happen that I think locate is much faster than find, and I still have hesitations with find that I should learn however, that's sure... – Stephane Rolland Feb 25 '13 at 23:32
  • A bit late to the discussion but remember that locate uses a previously constructed index/cache as its source of data (usually rebuild regularly with a cron job) which can be updated manually (typically with a sudo updatedb - it often needs elevated privileges to read some areas of the file-system!) c.f. find walks and reports on the file-system at run time so it will return current details at the time it finds them. In comparison locate is faster at the time you use it (especially if you have to refine/repeat your search) whereas find is more current in data it returns... – SlySven Aug 11 '16 at 1:37
5

Your command passes the output of locate to cat on standard-in. That's not what you want. What you want is to pass the output of locate to cat as an argument.

I believe the way to do that is with xargs:

locate pg_type.h | xargs cat
  • 2
    You can also do this with backticks or $(), eg cat $(locate pg_type.h). – goldilocks Feb 25 '13 at 23:20
  • 1
    That assumes none of the paths returned by locate contain any space, tab, newline, blackslash, single or double quote characters. And for $() (@goldilocks), no spc, tab, newline or globbing (*, ?, [) characters. – Stéphane Chazelas Feb 25 '13 at 23:29
  • @StephaneChazelas : Yep. But who would put silly things like that in a path? ;) ;) – goldilocks Feb 25 '13 at 23:38
  • 2
    @goldilocks, Windows/Mac users or anybody that may want to exploit the bug that you're introducing. For instance, if you run that line as root and the output ends up in somewhere world-readable, then somebody may want to create a file called /tmp/ /etc/shadow /pg_type.h to be able to have a look at the content of the /etc/shadow file. Remember some bugs end up being security vulnerabilities, some of which end up exploited. Lets try and have as few bugs as possible in the first place. And that starts with teaching good practice here (or at least mention the limitations/risks). – Stéphane Chazelas Feb 25 '13 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.