39

I want to redirect the output of the find command to cat command so I can print the data of the given file.

So for example if the output of find is /aFile/readme then the cat should be interpreted as cat ./aFile/readme. How can I do that instantly ?

Do I have to use pipes ?

I tried versions of this :

cat | find ./inhere -size 1033c 2> /dev/null

But I guess this is completely wrong? Of course I'm sure that the output is only one file and not multiple files.

So how can I do that ? I've searched on Google and couldn't find a solution, probably because I didn't search right :P

4 Answers 4

60

You can do this with find alone using the -exec action:

find /location -size 1033c -exec cat {} +

{} will be replaced by the files found by find, and + will enable us to read as many arguments as possible per invocation of cat, as cat can take multiple arguments.

If your find does not have the standard + extension, or you want to read the files one by one:

find /location -size 1033c -exec cat {} \;

If you want to use any options of cat, do:

find /location -size 1033c -exec cat -n {} +
find /location -size 1033c -exec cat -n {} \;

Here I am using the -n option to get the line numbers.

4
  • So, If I'm correct : {} is like a variable that in it is stored the output of the find command and after the "+" sign you're supposed to write the cat parameters ? No ? Edit : Alright you edited your post and now you just answered my question :P Thanx man ! Solved !
    – Eksapsy
    Jun 26, 2016 at 19:35
  • @general656 Check my edits..
    – heemayl
    Jun 26, 2016 at 19:37
  • 2
    The fact that I didn't know about cat's -n option surprises me. I love reading random questions.
    – mazunki
    Nov 29, 2019 at 19:32
  • 1
    Unfortunately, find /location -size 1033c -exec cat -n {} \; only opens the first file. Sep 6, 2020 at 1:25
12

Command Substitution

Another option is to use Command Substitution. Wrapping a command in $() will run the command and replace the command with its output.

cat $(find ./inhere -size 1033c 2> /dev/null)

will become

cat ./inhere/file1 ./inhere/file2 ./inhere/file3

This is more or less equivalent to using the older style of wrapping commands with back ticks:

cat `find ./inhere -size 1033c 2> /dev/null`

More details from the docs linked above

Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

Command substitutions may be nested. To nest when using the backquoted form, escape the inner backquotes with backslashes.

If the substitution appears within double quotes, word splitting and filename expansion are not performed on the results.

See this other answer for some good examples of usage.

1
  • 1
    Note that if find finds too many files, this would generate an "argument list too long" error whet trying to invoke cat. It would also have problems handling filenames containing whitespace characters and possibly also filenames containing filename globbing characters.
    – Kusalananda
    Oct 23, 2019 at 6:03
0

This will print the name and contents of text (ascii) files-only recursively..

find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'

One more attempt

find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
-2

Use pipe and xargs

find /* -name pg_hba.conf | xargs cat

If it fails because of lack of permissions, you can use sudo to make sure you have permission to execute find command on the directory you are searching.

 sudo find /* -name pg_hba.conf | xargs sudo cat
5
  • 2
    And if someone has created a file called /tmp/ /dev/urandom /pg_hba.conf, that will let root dump the whole content of /dev/urandom. Worse can probably be done depending on the context. xargs should almost never be used without -0 if at all. Also sudo xargs would be better than xargs sudo. And /* would be better as /. Jan 27, 2017 at 0:32
  • 1
    The OP wants to use cat to print the file content on stdout. So the purpose is served by cat. The question is how to use cat from the out put of find command to print the content of the file not how to use sudo or find , The above command solves the question. Yes xargs -0 was the only constructive thing you pointed. But did not show the usage. Try not to be rude.
    – App Work
    Jan 27, 2017 at 1:05
  • Sorry if that appeared rude. That was not the intention. I wanted to point out the limitations. Your answer shows bad practices (find|xargs without -0 should really be banned), hence the down vote. The output of find without -print0 is not post-processable reliably. -print0 is not standard. Having said that, standard sudo find / -name pg_hba.conf -exec cat {} + could also make you dump the content of /dev/urandom (for instance if someone created a symlink from /tmp/pg_hba.conf to it and there's no easy portable way around that that doesn't at least have a race condition). Jan 27, 2017 at 9:53
  • 2
    Let's not use sudo "just in case", shall we?
    – lindhe
    Jul 19, 2017 at 21:41
  • Well, it's better than running sudo rm -rf /
    – devinbost
    Jan 17, 2018 at 0:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .