У меня есть большая серия подпапок на моем Mac со случайным количеством CSV-файлов в каждом. То, что я хотел бы сделать, это объединить эти файлы в один файл для каждого каталога.
До сих пор я знаю, что могу объединить эти файлы cat * > mergedfile.csv
, но у меня есть проблемы, перебирающие все папки. Мне до сих пор удавалось объединить все виды вещей, но я не могу заставить это делать то, что я хочу точно.
Есть идеи, как лучше всего это сделать?
for DIR in ./subfolder/*
do
cat $dir/* > merged.csv
done
$DIR
и$dir
не одно и то же.Ответы:
С помощью
find
вы можете рекурсивно перечислить все файлы, которые соответствуют определенному критерию, например, имя файла.Разбив его,
find . -name "*.csv"
вы найдете все файлы CSV из текущей папки, в которой вы находитесь (.
), и цикл просто перебирает этот список, добавляя все вoutput.csv
файл.Но: Имена файлов с пробелами, заглушающими символами и символами новой строки здесь могут быть сложными. Более безопасным решением было бы просто использовать
exec
команду find.Здесь
'{}'
будет заменен поиск с именем файла. Длинные вопросы и ответы о том, почему это так и как обойти проблему, можно найти здесь .Теперь, если вы хотите создать по одному CSV-файлу для каждого каталога - извините, раньше этого не видели - я бы, вероятно, сделал что-то вроде этого:
Хотя приведенное ниже решение Франка, вероятно, более эффективно.
Конечно, обратите внимание на разницу между
>
и>>
. Первый всегда обрезает файл до нулевой длины перед записью в него, тогда как второй просто добавляет файл.Причина, по которой
cat *.csv > merged.csv
сработало и почему в вашем цикле это не сработает, заключается в том, что оболочка будет расширять подстановочный знак раньше, поэтому в основном она видит:... что, конечно, ничего не перезаписывает.
источник
В родительскую папку:
источник
Предполагая bash 4+ (проверьте с помощью
bash --version
), вы можете активировать globstar с помощьюshopt -s globstar
и циклически перебирать все каталоги (и только каталоги - конечные/
файлы исключаются) рекурсивно с**/
Если вы действительно хотите использовать все файлы в каталоге, а не только те, которые заканчиваются на
.csv
, тоЕсли вы хотите перейти только на один уровень, а не быть полностью рекурсивным, используйте
*/
вместо**/
.Ключевая ошибка в OP-скрипте (не говоря уже о том, что bash чувствителен к регистру) заключается в том, что он пытается записать содержимое всех файлов в один
.csv
файл и делает это таким образом, что каждая итерация цикла завершается напиши последнее.Если вы хотите , чтобы объединить все те
.csv
файлы рекурсивно в один файл, вы можете снова использовать globstarисточник