Преобразование таблиц .xls / .xlsx в несколько .csv на основе списка

9

Мне нужно преобразовать все листы одного файла .xls / .xlsx в .csv. Это будет сделано для всех файлов .xls во всех каталогах и подкаталогах (рекурсивно).

Шаг 1 : Получить имена листов всех .xls в .csv, используя:

for file in $(find . -name '*.xls' -o -name '*.xlsx');do in2csv -n "$file" > ${file%.xls}-sheetnames-list.csv; done

filename-sheetnames-list.csv может выступать в качестве списка:

sheetname1
sheetname2
sheetname3

Шаг 2 : Код для преобразования определенного листа в .csv с использованием in2csv:

in2csv --sheet "SHEETNAME" filename.xls > filename-SHEETNAME.csv

Как я могу получить каждое имя листа в .xls / x и написать каждый лист отдельно для всех каталогов, содержащих .xls / x?

in2csv --write-sheets "-" filename.xls > filename-sheet1.csv filename-sheet2.csv .... дает вывод только на sheet1.csv, не уверен, как получить все листы из этого.

csheth
источник
2
Почему бы не просто findкаждый .xls{,x}и перебрать каждый лист с помощью -exec?
десерт
1
@glennjackman это совершенно по теме, как и в Unix и Linux .
тердон

Ответы:

10

Вы можете просто поместить цикл в другой цикл.

Чтобы избежать ошибок, не используйте forс findрезультатами.

while IFS= read -r file; do
    while IFS= read -r sheet; do
        in2csv --sheet "$sheet" "$file" > "${file%.*}-${sheet}.csv"
    done < <(in2csv -n "$file")
done < <(find . -name '*.xls' -o -name '*.xlsx')
pLumo
источник
@ Муру ах дерьмо. Ты абсолютно прав. Я тестировал в среде, где IFS уже был изменен, поэтому, конечно, он распространялся вниз. Идиот . Спасибо, редактирование отменено.
Terdon
@RoVo первый вариант работает отлично. Второй, однако, не дает мне никакого вывода или ошибки. Я не уверен почему; для одного .xls in2csv --write-sheets "-" filename.xls > sheetname.csvдает только первый лист. Я не знаю, какую дополнительную информацию добавить, чтобы написать все листы. Это даст нам ключи к исправлению вашего кода.
csheth
1
ты обновился до этой версии 1.0.2? pip install csvkit -U, Я думаю, что это работает не то, что вам нравится, с простым сценарием из 1-го варианта у вас есть больше способов контролировать вывод, имена файлов и т. Д.
pLumo
все еще не работает с обновлением, и да, я бы предпочел использовать список, чем, --write-sheets может быть, вы можете установить этот альтернативный вариант в качестве другого ответа ... Я приму первый вариант в качестве ответа тогда. Спасибо @RoVo
csheth
1
Может быть, в целом хорошая идея иметь альтернативные варианты в другом ответе. Спасибо, рад, что смог помочь.
pLumo
6

Пропуск поиска и использование bash:

shopt -s globstar  # enable recursive globbing
for f in **/*.xls{,x}  # for files ending in .xls or .xlsx
do
    in2csv -n "$f" |   # get the sheetnames
      xargs -I {} bash -c 'in2csv --sheet "$2" "$1" > "${1%.*}"-"$2".csv' _ "$f" {} # {} will be replaced with the sheetname
done
Мур
источник
этот скрипт выглядит элегантно, но его вывод не filename-{}.csvсодержит данных. Я новичок и, похоже, не могу найти ошибку, отредактировав сценарий и прочитав его. Немного помощи?
csheth
@ChintanSheth мой плохой, я забыл, что перенаправление будет снаружи xargs. Исправлено, не так элегантно сейчас.
Муру
xargsи >это зло Вот почему я предпочитаю другой цикл, он менее подвержен ошибкам.
pLumo
@RoVo Я бы тоже пошел на другой цикл, просто хотел показать другой метод здесь.
Муру
Теперь это работает, но немного медленнее, чем ответ @RoVo.
17
3

Версия CSVKIT> 1.0.2 имеет встроенную функцию для записи всех листов:

--write-sheets: WRITE_SHEETS
                      The names of the Excel sheets to write to files, or
                      "-" to write all sheets.

Таким образом, вы можете попробовать следующее:

find . -name '*.xls' -o -name '*.xlsx' -exec in2csv --write-sheets "-" {} \;

Замечания:

Кажется, это не работает на 100%, как ожидалось. Но стоит попробовать, так как это первая версия с таким вариантом, возможно, в будущих версиях реализация будет лучше / проще.

pLumo
источник
0

Используйте Gnumeric:

ssconvert -S filename.xlsx filename.csv

чтобы получить один csvфайл на листе.

Джеймс Хиршорн
источник