0

I have this dir structure:

ParentDir | -- Child Dir1 | -- File One.txt -- File | -- Child Dir2 | -- File Two.txt -- File 

I'm trying to find out all the .txt files and count the sum total of number of lines in them, so I do something like this:

TXTFILES=$(find . -name '*.txt') cat $TXTFILES | wc -l 

but the problem is, I get,

cat: ./Child: No such file or directory cat: Dir2/File: No such file or directory cat: Two.txt: No such file or directory cat: ./Child: No such file or directory cat: Dir1/File: No such file or directory cat: One.txt: No such file or directory 

How do I handle spaces in the Dir & File names in such a situation? Is it possible without using a loop?

0

4 Answers 4

4

If you don't need to store the file names in a variable, you can do this in 1 line:

find . -name '*.txt' -print0 | xargs -0 wc -l 

find supports a -print0 option that makes it use a null byte, rather than a space, to separate the file names. xargs supports a -0 (hyphen zero) switch to tell it the incoming file names are separated by a null byte rather than a space.

Sign up to request clarification or add additional context in comments.

2 Comments

... | xargs -0 cat -- | wc -l would produce output more like what the OP is looking for.
@Kenster - Yes, perfect.
3
find . -name '*.txt' -exec cat -- '{}' ';' | wc -l 

This runs cat individually for each file (which is less than ideal), but the filename is passed directly from find to cat without being parsed by the shell. So the filename could be anything that's problematic on the command line.

2 Comments

if you use + instead of ; it'll batch up the arguments to cat as far as possible.
This works, with the exact same output I was hoping for, and in the exact format I was expecting. :)
0

dirty and quick:

ls -1FR|grep -c '\.txt$' 

zsh:

ls **/*.txt|wc -l 

4 Comments

The second will work in bash 4.x as well if shopt -s globstar is used, although in either shell you can (and should) use wc -l **/*.txt instead.
@chepner wc -l **/*.txt does something else than ls **/*.txt|wc -l, doesn't it?
wc -l **/*.txt and cat **/*.txt | wc -l are slightly different, although the total line length of all the files is present in the output. ls **/*.txt | wc -l is quite different from what the OP asked; it gives the number of matching files.
@chepner ah!!!! I misunderstood the question. I thought he wanted to have the result ls ..|wc -l ....my bad... pending to remove
0

You can surround your files name path by " " like this

find . -name '*.txt' | sed -e 's/^/"/g' -e 's/$/"/g' | wc -l 

Example :

prompt$ touch a.txt "a a.txt" prompt$ find . -name '*.txt' | sed -e 's/^/"/g' -e 's/$/"/g' "./a a.txt" "./a.txt" prompt$ find . -name '*.txt' | sed -e 's/^/"/g' -e 's/$/"/g' | wc -l 2 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.