MacOS - объединить несколько текстовых файлов в одну электронную таблицу с одним файлом на столбец?

Используя терминал MacOS, можно ли взять каталог текстовых файлов и объединить их в одну электронную таблицу (в формате CSV или Numbers), поэтому:

  • Каждый файл находится в отдельной колонке
  • Каждая строка txt файла находится в отдельной строке.
  • Файлы размещаются в электронной таблице в алфавитном порядке (используя первую букву имени файла текстового файла).

Пример 1: вот как выглядят мои текстовые файлы перед объединением:

Пример 2: вот как мои текстовые файлы должны выглядеть в электронной таблице после объединения:

(Эти примеры являются частичным извлечением. На самом деле мне нужно объединить сотни файлов).


Шаги, которые я пробовал:

  1. Я искал ответ в Stack Overflow, но все остальные вопросы по этой задаче используют Python или Panda. Я бы предпочел решение, которое можно было бы сделать непосредственно из терминала MacOS без необходимости установки таких пакетов, как Python или Panda.

  2. Из исследований я считаю, что можно использовать команду paste:

    paste -d '\t' *.txt > ^0-merged.csv

Однако, когда я пытаюсь это сделать, появляется следующее сообщение об ошибке: paste: Too many open files. Он также создает совершенно пустой файл CSV.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
78
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете прокручивать добавление каждого файла.

touch merged.csv
for f in *.txt; do paste -d '\t' $f merged.csv > temp; cp temp merged.csv; done; rm temp

Сначала вы должны создать файл, так как вставка не удастся, если он не сможет найти файл.

https://unix.stackexchange.com/questions/205642/объединение большого количества файлов

Добавление новой идеи для файлов с пробелами.

#!/bin/bash
touch merged.csv

# save and change IFS
OLDIFS=$IFS
IFS=$'\n'
 
# read all file name into an array
fileArray=($(find ./ -name "*.txt" | sort))
 
# restore it
IFS=$OLDIFS
 
# get length of an array
tLen=${#fileArray[@]}
 
# use for loop read all filenames
for (( i=0; i<${tLen}; i++ ));
do
  paste -d '\t' "${fileArray[$i]}" merged.csv > temp; 
  cp temp merged.csv; 
done
rm temp

Спасибо, это работает отлично. За исключением того, есть ли какой-либо способ получить его, поэтому он размещает текстовые файлы в столбце в алфавитном порядке имен файлов (извините, я забыл указать алфавитную часть в своем вопросе. Я так привык, что все мои файлы отображаются в в алфавитном порядке в папке, которую я забыл упомянуть!)

big_smile 17.04.2023 13:51

Если у вас нет пробелов в именах файлов, то это должно работать for f in `ls *.txt | sort`; do paste -d '\t' $f merged.csv > temp; cp temp merged.csv; done; rm temp

nowait 17.04.2023 15:24

Спасибо! В моих файлах действительно есть пробелы в именах файлов. Любая работа для этого? Заранее спасибо.

big_smile 17.04.2023 15:47

Я обновил его с новой идеей. Просто поместите это в скрипт и запустите.

nowait 17.04.2023 17:18

Потенциальная проблема здесь заключается в том, что если файлы имеют разную длину, столбцы не будут заполнены, чтобы соответствовать более длинным столбцам.

dawg 17.04.2023 17:46

@nowait Это работает, примите, что это происходит в обратном порядке имен файлов (например, от z-A). Можно ли как-то перевернуть его, чтобы он шел от AZ? Кроме того, похоже, что прописные буквы AZ и строчные буквы AZ рассматриваются как отдельные (например, имена файлов с AZ будут идти первыми, а затем имена файлов с AZ). Он также распечатывает это сообщение об ошибке, я не уверен, что это приводит к неправильному порядку: rm temp zsh: command not found: # zsh: command not found: # zsh: command not found: # zsh: command not found: # zsh: command not found: # paste: : No such file or directory

big_smile 17.04.2023 19:33

изменение fileArray=($(find ./ -name "*.txt" | sort)) на fileArray=($(find ./ -name "*.txt" | sort -r)) изменит порядок. И если вы добавите #!/bin/bash в качестве первой строки скрипта, он сообщит ему, какую оболочку использовать.

nowait 17.04.2023 19:41
Ответ принят как подходящий

Руби является частью MacOS.

Данный:

head -n 3 *.txt
==> GOOD THINGS IN LIFE.txt <==
Art
Fun
Hugs

==> IN THE BACKYARD.txt <==
Hose
Tree
Soil

==> KITCHEN CUPBOARD ESSENTIALS.txt <==
Tea
Rice
Milk

==> KNITTING STITCHES.txt <==
Rib
Dip
Seed

# and the rest of your lines in each case...

Ты можешь сделать:

ruby -e '
a=[]
ARGV.sort.each{|fn|
    a<<[fn]+File.open(fn).read.split(/\R/)
}
a.transpose.each{|sa|
    puts sa.join(",")
}
' *.txt

Отпечатки:

GOOD THINGS IN LIFE.txt,IN THE BACKYARD.txt,KITCHEN CUPBOARD ESSENTIALS.txt,KNITTING STITCHES.txt
Art,Hose,Tea,Rib
Fun,Tree,Rice,Dip
Hugs,Soil,Milk,Seed
Earth,Fence,Salt,Tile
Honor,Porch,Pesto,Linen
Space,Patio,Flour,Cable
Sport,Grass,Honey,Wicker
Intelligence,Wading Pool,Baking Powder,Knotted Boxes
Innovation,Welcome Mat,Vegetable Oil,Chinese Wave
Confidence,Back Stoop,Tomato Paste,Checkerboard
Good Deeds,Fruit Tree,Black Pepper,Herringbone
Creativity,Downspout,Baking Soda,Stockinette
Education,Birdbath,Ketchup,Garter
Kindness,Terrace,Surer,Waffle
Integrity,Planter,Sugar,Puri Ridge
Faith,Carport,Coffee,Netted
Friends,Flowerbed,Cinnamon,Elongated
Respect,Shovel,Cheese,Farrow Rib
People,Hedges,Bread,Plaited
Yourself,Rocks,Olive Oil,Clamshell
Happiness,Lawnmower,Crackers,Bamboo
Heart,Hot Tub,Pasta,English Rib
Religion,Garden,Scissors,Basket
Wisdom,Stoop,Garlic,Raspberry

Если вам нужен «правильный» CSV с полями в кавычках, который лучше работает с Excel, вы можете использовать модуль CSV, включенный в Ruby:

ruby -r csv -e '
a=[]
ARGV.sort.each{|fn|
    a<<[fn]+File.open(fn).read.split(/\R/)
}
a=a.transpose
puts CSV.generate(**{headers:true, quote_empty:true, force_quotes:true}){|csv|
    csv<<a[0]
    a[1..].each{|row|
        csv<<row
    }
}
' *.txt

Отпечатки:

"GOOD THINGS IN LIFE.txt","IN THE BACKYARD.txt","KITCHEN CUPBOARD ESSENTIALS.txt","KNITTING STITCHES.txt"
"Art","Hose","Tea","Rib"
"Fun","Tree","Rice","Dip"
"Hugs","Soil","Milk","Seed"
"Earth","Fence","Salt","Tile"
"Honor","Porch","Pesto","Linen"
"Space","Patio","Flour","Cable"
"Sport","Grass","Honey","Wicker"
"Intelligence","Wading Pool","Baking Powder","Knotted Boxes"
"Innovation","Welcome Mat","Vegetable Oil","Chinese Wave"
"Confidence","Back Stoop","Tomato Paste","Checkerboard"
"Good Deeds","Fruit Tree","Black Pepper","Herringbone"
"Creativity","Downspout","Baking Soda","Stockinette"
"Education","Birdbath","Ketchup","Garter"
"Kindness","Terrace","Surer","Waffle"
"Integrity","Planter","Sugar","Puri Ridge"
"Faith","Carport","Coffee","Netted"
"Friends","Flowerbed","Cinnamon","Elongated"
"Respect","Shovel","Cheese","Farrow Rib"
"People","Hedges","Bread","Plaited"
"Yourself","Rocks","Olive Oil","Clamshell"
"Happiness","Lawnmower","Crackers","Bamboo"
"Heart","Hot Tub","Pasta","English Rib"
"Religion","Garden","Scissors","Basket"
"Wisdom","Stoop","Garlic","Raspberry"

Комментарии:

Он также помещает имя файла вверху каждого столбца. Есть ли способ опустить имя файла? Кроме того, он, кажется, обрабатывает прописные буквы AZ и строчные буквы az как отдельные (например, имена файлов с буквами AZ будут первыми а потом имена файлов через a-z) Спасибо!

Если у вас есть файлы разной длины, вы можете дополнить конец более коротких файлов, чтобы у вас все еще была правильная матрица для транспонирования:

ruby -r csv -e '
a=[]
ARGV.sort_by{|s| s.downcase}.each{|fn|
    a<<File.open(fn).read.split(/\R/)
}
max_length=a.max_by{|sa| sa.length}.length
a.each.with_index{|sa,i| 
    if sa.length<max_length then a[i].concat [""]*(max_length-sa.length) end }
a=a.transpose
puts CSV.generate(**{headers:true, quote_empty:true, force_quotes:true}){|csv|
    csv<<a[0]
    a[1..].each{|row|
        csv<<row
    }
}
' *.txt

Спасибо! Когда я пытаюсь это сделать, в терминале появляется эта ошибка --e:6:in transpose': element size differs (36 should be 27) (IndexError) from -e:6:in <main>' ` Есть идеи?

big_smile 17.04.2023 15:46

Это связано с тем, что ваши файлы различаются по размеру, а ваш пример имеет одинаковые размеры. Вы можете сделать их все одинаковой длины (что тривиально в Ruby), но возникает вопрос: какие строки тогда считать пустыми? Все в конце?

dawg 17.04.2023 17:02

@dwag Спасибо, это работает! А есть ли возможность вывода в файл, а не отображения в терминале. Он также помещает имя файла вверху каждого столбца. Есть ли способ опустить имя файла? Кроме того, похоже, что прописные буквы A-Z и строчные буквы az рассматриваются как отдельные (например, сначала будут идти имена файлов с A-Z, а затем имена файлов с az). Спасибо!

big_smile 17.04.2023 19:34

Для вывода в файл просто перенаправьте вывод в zsh / Bash с помощью > output_file сразу после *.txt в этом случае. Другие элементы, исправленные в последней версии.

dawg 17.04.2023 20:13

Другие вопросы по теме