map, fold and filter can approximate the pipeline pretty well. Personally I only use shell scripting when I actually want to record a set of commands I ran (or, well, when working in a shell); in all other cases I whip out proper tools.
Here's a comparison of code to do the same thing written in Ruby:
Dir['**/*.py'].map{|f| File.readlines(f).length }.inject(:+)
find . -name '*.py' | xargs cat | wc -l
That's 60 characters versus 39 (most of these are just because the "commands" are longer – and I don't think anyone would even try to argue that 'cat' or 'wc' is more readable than 'File.readlines' or 'length').
I ran them on Python 2.7's library directory and my version counted four lines more – I didn't investigate, but I think yours missed lines when cating files without trailing newline. I'd argue that's a bug in your code :)