With find, you can recursively list all files that match a certain criterion, e.g. the file name.
for file in $(find . -type f -name "*.csv"); do cat "$file" >> /path/to/output.csv; done
Breaking it up, find . -name "*.csv" will find all CSV files from the current folder you're in (.), and the loop will just iterate over that list, appending everything to the output.csv file.
But: File names with spaces, globbing characters, and newlines can be tricky here. A safer solution would be to just use exec for the find command.
find . -name "*.txt" -exec cat '{}' >> /path/to/output.csv ';'
Here, '{}' will be replaced by find with the filename. For a long Q&A about why this is and how to circumvent the problem can be found here.
Now, if you want to create one CSV file for each directory – sorry, didn't see that before –, I'd probably do something like this:
for dir in $(find . -type d); do find $dir -maxdepth 1 -name "*.csv" -exec cat {} >> "$dir/out" ';'; mv "$dir/out" "$dir/merged.csv"; done
Although Franck's solution below is probably more efficient.
Of course, pay attention to the difference between > and >>. The former will always truncate the file to zero-length before writing to it, whereas the latter will just append to the file.
The reason why cat *.csv > merged.csv worked—and why in your loop, it won't work—is that the shell will expand the wildcard before, so basically it sees:
cat file1.csv file2.csv file3.csv > merged.csv
… which will of course not overwrite anything.
$DIRand$dirare not the same thing. – choroba Dec 1 '11 at 13:07