Why does pipe not work with cat and locate

catlocatepipe

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.

Best Answer

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.