0

I'm learning about expansion/ command substitution, and while paying around with an example, noticed that these two commands have different results.

For example, if I cd into /usr/bin, and run ls | grep zip, grep picks up "zip" in the file names only.

But when I run grep zip $(ls) in the same directory, grep also picks up zip in the file content. Why? Ubuntu 16.04.

I know it's a newbie question, but it would still be helpful to know why. Thanks.

cmak.fr
  • 8,986
mxr
  • 45
  • 1
  • 8
  • I'm not using double quotes on the command line, just the commands that are shown in double quotes above. – mxr Jun 01 '18 at 14:41
  • That's because grep looks into files. In the second example, you give a list of files to be looked into, while the first one acts like a simple string. – Gergely Lukacsy Jun 01 '18 at 15:01
  • Please read https://mywiki.wooledge.org/ParsingLs More sensible approach would be find -type f -name "*.zip" – Sergiy Kolodyazhnyy Jun 01 '18 at 17:57

1 Answers1

9

This is because grep can operate in two distinct modes:

DESCRIPTION
   grep searches the named input FILEs for lines containing a match to the
   given PATTERN.  If no files are specified, or if the file “-” is given,
   grep  searches  standard  input.   By default, grep prints the matching
   lines.

In ls | grep zip, the grep command sees a list of filenames on its standard input and searches that.

In grep zip $(ls), the shell substitutes the results of the ls command as a list words, which grep treats as filename arguments, searching each one in turn for the pattern zip.

IMPORTANT NOTE: if any of the filenames contain spaces, then the space-separated parts will be treated as separate arguments, resulting in No such file or directory errors. A safer way to search matching files is to use shell globs e.g. grep 'pattern' *zip*

steeldriver
  • 143,099