Com find
, você pode listar recursivamente todos os arquivos que correspondem a um determinado critério, por exemplo, o nome do arquivo.
for file in $(find . -type f -name "*.csv"); do cat "$file" >> /path/to/output.csv; done
Quebrando, find . -name "*.csv"
encontrará todos os arquivos CSV da pasta atual em que você está ( .
), e o loop apenas fará uma iteração sobre essa lista, anexando tudo ao arquivo output.csv
.
Mas: Nomes de arquivos com espaços, caracteres globbing e novas linhas podem ser complicados aqui. Uma solução mais segura seria usar apenas exec
para o comando find.
find . -name "*.txt" -exec cat '{}' >> /path/to/output.csv ';'
Aqui, '{}'
será substituído pelo nome do arquivo. Por um longo Q & A sobre por que isso é e como contornar o problema pode ser encontrado aqui .
Agora, se você quiser criar um arquivo CSV para cada diretório - desculpe, não vi isso antes -, provavelmente faria algo assim:
for dir in $(find . -type d); do find $dir -maxdepth 1 -name "*.csv" -exec cat {} >> "$dir/out" ';'; mv "$dir/out" "$dir/merged.csv"; done
Embora a solução de Franck abaixo seja provavelmente mais eficiente.
Claro, preste atenção à diferença entre >
e >>
. O primeiro sempre truncará o arquivo com comprimento zero antes de gravar nele, enquanto o segundo apenas anexará ao arquivo.
A razão pela qual cat *.csv > merged.csv
funcionou - e por que, no seu loop, não funcionará - é que o shell expandirá o curinga antes, então basicamente ele vê:
cat file1.csv file2.csv file3.csv > merged.csv
… o que obviamente não substituirá nada.