-3

I tried to figure out what is the difference those commands (for a school project), but for me its chrashed or running for more than 10min~

So, the sample:

sudo find / -type f -exec file ’{}’ ; | grep ’Shell script’ | wc -l

the differences:

#without ' ' at {}

  1. sudo find / -type f -exec file {} \; | grep ’Shell script’ | wc -l
    

#without the \

  1. sudo find / -type f -exec file ’{}’ ; | grep ’Shell script’ | wc -l
    

#without ' ' after grep command

  1. sudo find / -type f -exec file ’{}’ \; | grep Shell script | wc -l
    

Thanks for your time, and help.

1

1 Answer 1

1

First of all, you need to use straight quotes ('), not typographical ones, as noted by steeldriver.

Second, the effect of the presence of quotes or not makes a difference in what the command itself receives:

For example, you could have:

echo 'semicolon ; echo message'

Here the command echo¹ is run with the parameter semicolon ; echo message. And thus the output would be a line saying

semicolon ; echo message

Now suppose that there were no quotes:

echo semicolon ; echo message

The program echo would function exactly in the same way (printing the parameter). However, the difference is that, since ; is a special character for the shell, the shell itself would treat the line differently, as two commands:

  • echo semicolon
  • echo message

The output would be:

semicolon message

There are three places on your lines that may be quoted or not:

  • {}

As noted on GNU find and masking the {} for some shells - which? most shells won't require quoting a standalone {}, and thus it won't make a difference.

  • ;

find requires a ; to finish the single-argument -exec. As ; is special for the shell, it needs to be quoted (as \;, ';' or ";", it doesn't matter, just not as a literal ;). Otherwise _the shell_would interpret it as a find command, then a second command starting with a pipe (|), which leads to a shell error:

syntax error near unexpected token `|'

  • Shell script

For the grep you have two very different outputs. In the first case, you call grep with a single argument (Shell script). In the other, it is called with two arguments (first Shell, second script). Given the way grep works, in the first case it would look for lines received on its input that contain the text Shell script. In the second, it would look for lines containing the text Shell in a file named script. Which are quite different behaviors.

This information should let you figure out which would be the right line to run, and the reason to write it that way.

¹ Actually a shell builtin will be called, but let's assume it's the standalone /bin/echo the one that runs.


Finally, the correct line does three things.

  • Run the command file _on each and every file of your system`
  • Select those lines (describing those files) that contain the text Shell script
  • Count the number of lines (and thus of shell scripts)

(the last command would be equivalent to using grep -c)

As such, you won't receive the output of the command (which is a number) until after running a program thousands and thousands of times (one per entry in your filesystem), so it's perfectly normal that it takes a long time to run.

You can run it inside a folder skipping the / so it only searches that subtree.

Another way to see what it is doing would be to insert a tee /dev/stderr on the pipeline:

find / -type f -exec file {} \; | tee /dev/stderr | grep "Shell script" | wc -l
1
  • @roaima Indeed. You could get the same effect with backslash escapes. I was referring on wheteher or not to have quotes there. I mentioned the equivalence later on ;, although I didn't want to get into the difference of single and double quotes, nor in the more exotic quotings.
    – Ángel
    Nov 3, 2020 at 0:07

You must log in to answer this question.

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