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.
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communitylocate -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.
locate
is much faster than find
, and I still have hesitations with find
that I should learn however, that's sure...
Feb 25, 2013 at 23:32
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...
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
$()
, eg cat $(locate pg_type.h)
.
Feb 25, 2013 at 23:20
$()
(@goldilocks), no spc, tab, newline or globbing (*
, ?
, [
) characters.
Feb 25, 2013 at 23:29
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).
Feb 25, 2013 at 23:46
locate(1)
, and sending its output to the input ofcat(1)
, which dutifully copies its input to its output. Nothing to see here, move along.locate
is not reliable for information about what is on your filesystem right now.