С помощью find
вы можете рекурсивно перечислить все файлы, которые соответствуют определенному критерию, например, имя файла.
for file in $(find . -type f -name "*.csv"); do cat "$file" >> /path/to/output.csv; done
Разбейте его, find . -name "*.csv"
найдет все файлы CSV из текущей папки, в которой вы находитесь (.
), и цикл будет просто перебирать этот список, добавляя все в файл output.csv
.
Но: Имена файлов с пробелами, заглушающими символами и символами новой строки здесь могут быть сложными. Более безопасным решением было бы просто использовать exec
для команды find.
find . -name "*.txt" -exec cat '{}' >> /path/to/output.csv ';'
Здесь '{}'
будет заменено на find с именем файла. Длинные вопросы и ответы о том, почему это так и как обойти проблему, можно найти здесь.
Теперь, если вы хотите создать по одному CSV-файлу для каждого каталога - извините, раньше этого не видели - я бы, вероятно, сделал что-то вроде этого:
for dir in $(find . -type d); do find $dir -maxdepth 1 -name "*.csv" -exec cat {} >> "$dir/out" ';'; mv "$dir/out" "$dir/merged.csv"; done
Хотя приведенное ниже решение Франка, вероятно, более эффективно.
Конечно, обратите внимание на разницу между >
и >>
. Первый всегда обрезает файл до нулевой длины перед записью в него, тогда как второй просто добавляет файл.
Причина, по которой cat *.csv > merged.csv
сработала - и почему в вашем цикле это не сработает, - в том, что оболочка расширила подстановочный знак раньше, поэтому в основном она видит:
cat file1.csv file2.csv file3.csv > merged.csv
... что, конечно, ничего не перезаписывает.