I'm trying to count the total lines in the files within a directory. To do this I am trying to use a combination of find and wc. However, when I run find . -exec wc -l {}\;, I recieve the error find: missing argument to -exec. I can't see any apparent issues, any ideas?
2 Answers
You simply need a space between {} and \;
find . -exec wc -l {} \; Note that if there are any sub-directories from the current location, wc will generate an error message for each of them that looks something like that:
wc: ./subdir: Is a directory To avoid that problem, you may want to tell find to restrict the search to files :
find . -type f -exec wc -l {} \; Another note: good idea using the -exec option . Too many times people pipe commands together thinking to get the same result, for instance here it would be :
find . -type f | xargs wc -l The problem with piping commands in such a manner is that it breaks if any files has spaces in it. For instance here if a file name was "a b" , wc would receive "a" and then "b" separately and you would obviously get 2 error messages: a: no such file and b: no such file.
Unless you know for a fact that your file names never have any spaces in them (or non-printable characters), if you do need to pipe commands together, you need to tell all the tools you are piping together to use the NULL character (\0) as a separator instead of a space. So the previous command would become:
find . -type f -print0 | xargs -0 wc -l 1 Comment
+ in place of ';' (or \;) works more or less the same as using xargs; find groups a bunch of file names together to run the command once per N file names (where N is not a controllable quantity, but depends on the maximum length of an argument list and the length of the file names).With version 4.0 or later of bash, you don't need your find command at all:
shopt -s globstar wc -l **/* There's no simple way to skip directories, which as pointed out by Gui Rava you might want to do, unless you can differentiate files and directories by name alone. For example, maybe directories never have . in their name, while all the files have at least one extension:
wc -l **/*.*
find . -exec wc -l {} \;(space before\;).