0

I'm having trouble with grep's manner of interpreting "recursive" searching compared to cp. Maybe it's just that I use them differently.

In this, grep seems to interpret "recursive" differently from cp. Is that correct? (my question)

Per my Question to navigate through this on SO...

With files containing the grep-matched string:

./file1.js
./file2.php
./inc/file3.js
./inc/file4.php
./inc.php/file5.php
grep -R "find me" *.php

Returns:

./file2.php
./inc.php/file5.php

...because grep wants to match both directories and files containing ".php"

But, if I use cp to copy recursively, say:

cp -r inc/* ~/mywork/

Files in the "inc" folder will be copied, along with all directories et cetera, albeit not hidden files, regardless of whether they have "inc" in their name.

Do grep and cp have different meanings of "recursive" or do they treat "recursive" the same? Could someone help me understand how different path/file arguments are interpreted by cp and grep the same way?

1
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Kusalananda
    Commented May 15, 2022 at 14:11

1 Answer 1

4

Your grep command,

grep -R "find me" *.php

... contains a filename globbing pattern, *.php. This will be expanded by the shell before the shell executes grep, so the actual command at execution may look something like

grep -R "find me" file1.php file2.php inc.php

... where inc.php happens to be a directory name.

The grep utility would then search the given files for the expression that you provided. For directories mentioned on the command line, it would search all files and subdirectories beneath the directory for files with contents matching the expression. This means you would have found a match in inc.php/subdir/README had that file contained the string find me.

In short: Process (search for matching lines within) each name given on the command line according to the given options (recursively).

The cp command works the same way with regards to recursive actions:

cp -r inc/* ~/mywork/

The shell would expand the above command to something like

cp -r inc/file1 inc/file2 inc/dir1 inc/dir2 /home/myself/mywork/

The cp utility would then, for each individually named file or directory, copy that file or directory recursively to the destination directory.

In short: Process (copy to destination) each name given on the command line according to the given options (recursively).


Additional notes:

  • The support in grep for searching recursively is a non-standard extension.

  • Filename globbing patterns that may expand to names starting with a dash should be handled with care to not be confused with command-line options. Your grep command is, therefore, more safely written as

    grep -R -- "find me" *.php
    

    or as

    grep -R -e "find me" -- *.php
    

    ... where -- delimits the options and their arguments from the non-option operands. Your cp command does not have that issue, as the globbing pattern is guaranteed to expand to something starting with the string inc/.

You must log in to answer this question.

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