Разделите файл на строку и получите контроль над полученным расширением файла

28

Существует стандартная команда для разделения файлов - split.

Например, если я хочу разбить файл слов на несколько частей по 10000 строк, я могу использовать:

split -dl 10000 words wrd

и он будет генерировать несколько файлов в формате wrd.01, wrd.02 и так далее.

Но я хочу иметь конкретное расширение для этих файлов - например, я хочу получить файлы wtd.01.txt, wrd.02.txt.

Есть ли способ сделать это?

Рогач
источник

Ответы:

12

Не с split, но вы можете легко переименовать их впоследствии, или вы можете сделать это в awk:

awk '{filename = "wrd." int((NR-1)/10000) ".txt"; print >> filename}' inputfile
Kevin
источник
Выглядит хорошо - но не работает. В вашей форме жалуется на то, что «выражение для перенаправления >> >> имеет нулевое строковое значение», а если «file» «изменено» на «filename», выводит файлы вида wrd. {File number}. {Номер строки} .txt (их довольно много :)
Рогач
@Rogach Извините, я не проверял это, поэтому я забыл, что awk не выполняет целочисленное деление. Я проверил это.
Кевин
49

Тогда это было недоступно, но с более поздними версиями ( ≥ 8.16) gnu splitможно использовать --additional-suffixкоммутатор для контроля над полученным расширением. От man split:

--additional-suffix=SUFFIX
              append an additional SUFFIX to file names.

поэтому при использовании этой опции:

split -dl 10000 --additional-suffix=.txt words wrd

результирующие куски будут автоматически заканчиваться на .txt:

wrd00.txt
wrd01.txt
.........
don_crissti
источник
3
Не работает на Mac
Ericgu
2
Я люблю твой сарказм. Я Unix N00B из мира Apple. Я использую OS X Yosemite, и я просто не хотел, чтобы другие рухнули и сгорели, как я. Я проверял и проверял документы, и у нас нет этого параметра. Я мог что-то пропустить. developer.apple.com/library/mac/documentation/Darwin/Reference/...
ericgu
5
@swiftshokunin - мой ответ относится к gnu splitчасти gnu coreutils. Он также доступен в OSX, если вы устанавливаете coreutilsчерез, homebrewно обратите внимание, что по умолчанию в OSX gnuслужебные программы имеют gпрефикс перед своим именем (например, gstatвместо stat), поэтому вы вызываете его как gsplit(или изменяете PATH согласно руководству здесь, если хотите). использовать его как splitповерх OSX split). НТН.
don_crissti
1
Хороший ответ. в OS X используйте, gsplitчтобы заставить работать числовые суффиксы (-d).
Брент Фауст
1
вау, я понятия не имел, что есть gsplit - он, вероятно, из упомянутых выше coreutils и имеет --additional-суффикс. Спасибо всем, кто комментирует это решение :)
Łukasz Rysiak
13

Такие задачи лучше всего решать с помощью оболочки. Используйте split, а затем напишите простой цикл, чтобы переименовать файлы. Например

for file in wrd.*
do
    mv "$file" "$file.txt"
done

переименовал бы ваши файлы wrd.01, wrd.02 и т. д., чтобы все они имели расширение .txt.

Кайл Джонс
источник
Это совершенно очевидно, но это нарушило бы краткость сценария bash.
Рогач
1
Философия Unix состоит в том, чтобы предоставить вам набор простых инструментов, которые вы затем комбинируете для выполнения работы. «Краткость сценария bash» не была заявленным требованием в вашем вопросе.
Кайл Джонс
7
PS: split+mvкомбо более , что в 6 раз быстрее , чем awk(примерно 3 сек против 18s ) для входного файла 10000000 линии (75 MB) ... текст в каждой строке была своя линия номер ... Спасибо за Перефразирование «очевидное» :)
Peter.O
3
PPS: Я только что проверил это немного дальше. Разница в скорости связана с количеством созданных файлов против числа форматирования и арифметических вычислений, которые awk выполняет для каждой строки независимо от количества выходных файлов ... Использование того же входного файла, что и в приведенном выше примере: В 100 раз меньше файлов, split + mvв 75 раз быстрее, чем awk: Когда в 100 раз больше файлов, split + mvв 1,5 раза быстрее, чем awk. Так что для меня этот split + mvметод побеждает, руки вниз. Это как consice (возможно, более того), и быстрее, чем awk.
Peter.O
1
если вы обеспокоены тем, что длина составляет 5 строк, попробуйте вместо этого: for file in wrd.*; do mv "$file" "$file.txt"; done:)
Тони