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.

  • I'm not using double quotes on the command line, just the commands that are shown in double quotes above.
    – mxr
    Jun 1, 2018 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. Jun 1, 2018 at 15:01
  • Please read mywiki.wooledge.org/ParsingLs More sensible approach would be find -type f -name "*.zip" Jun 1, 2018 at 17:57

1 Answer 1


This is because grep can operate in two distinct modes:

   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

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*

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.