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 `|'
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
’smart quotes’
with regular'ASCII quotes'
- then have a read of these: Special meaning of '{}' ';' with find and GNU find and masking the {} for some shells - which? – steeldriver Nov 01 '20 at 23:57