Кратко: split — разделяем файлы
Давненько я тут не писал, хотя заметок накопилось немало.. и начну я пока с кратких заметок. Сегодня речь пойдет об утилите split. Данная утилита позволяет разбивать файлы на несколько частей.
Когда это может быть полезным? Ну к примеру вам может потребоваться разделить большой лог-файл для того, чтобы было удобнее анализировать его на наличие ошибок. Второй вариант — разделить большой архив (что мне и потребовалось) для того, чтобы загрузить его частями на облако, в котором есть ограничения по размеру файлов…
Ниже будет представлено несколько вариантов использования этой утилиты, и начну я с самого распространенного.
Как разделить большой архив на несколько файлов по 15gb?
Самый простой способ:
split -b 15G ./archive.tar.gz
В результате вы получите файлы, начинающиеся с префикса «x»:
# ls -lah x*
-rw-r--r-- 1 root root 15G янв 16 21:56 xaa
-rw-r--r-- 1 root root 15G янв 16 21:56 xab
-rw-r--r-- 1 root root 15G янв 16 21:56 xac
А как сделать тоже самое, только с нормальным именем?
В этой ситуации достаточно добавить желаемую маску, указав ее в кавычках после выбранного файла:
split -b 15G ./archive.tar.gz "archive.tar.gz."
В результате архив будет разделен на эти файлы:
# ls -lah archive.tar.gz*
-rw-r--r-- 1 root root 15G янв 16 22:05 archive.tar.gz.aa
-rw-r--r-- 1 root root 15G янв 16 22:05 archive.tar.gz.ab
-rw-r--r-- 1 root root 15G янв 16 22:05 archive.tar.gz.ac
Как заменить эти aa ab на цифры?
Вместо «буквенного» суффикса есть и «цифровой». Чтобы им воспользоваться достаточно использовать ключ -d:
split archive.tar.gz -b 15G -d "archive.tar.gz."
Результат будет такой:
# ls -lah archive.tar.gz.*
-rw-r--r-- 1 root root 15G янв 16 22:55 archive.tar.gz.00
-rw-r--r-- 1 root root 15G янв 16 22:55 archive.tar.gz.01
-rw-r--r-- 1 root root 15G янв 16 22:55 archive.tar.gz.02
-rw-r--r-- 1 root root 15G янв 16 22:55 archive.tar.gz.03
-rw-r--r-- 1 root root 15G янв 16 22:55 archive.tar.gz.04
-rw-r--r-- 1 root root 15G янв 16 22:55 archive.tar.gz.05
Что еще можно сделать с суффиксом?
Можно увеличить его длину (по умолчанию длина суффикса — 2). Сделать это можно, например до 4, с помощью ключа «-a 4»:
split -b 15M ./archive.tar.gz "archive.tar.gz." -a 4
Результат:
# ls -lah archive.tar.gz*
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaaa
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaab
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaac
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaad
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaae
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaaf
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaag
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaah
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaai
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaaj
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaak
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaal
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaam
-rw-r--r-- 1 root root 15M янв 16 23:15 archive.tar.gz.aaan
-rw-r--r-- 1 root root 11M янв 16 23:15 archive.tar.gz.aaao
Еще можно использовать шестнадцатеричный суффикс, воспользовавшись ключом «-x». Но на нем я не буду останавливаться.
Как разделить архив на два файла?
Тут нам поможет ключ -n:
split archive.tar.gz archive.tar.gz_ -n2
В результате мы получим два файла, разделенные «пополам» как и хотели:
ls -lah archive.tar.gz*
-rw-r--r-- 1 root root 111M янв 16 22:20 archive.tar.gz_aa
-rw-r--r-- 1 root root 111M янв 16 22:20 archive.tar.gz_ab
А как теперь собрать все части в один архив?
Это нельзя сделать с помощью split, но можно с помощью cat. Ниже пример того, как я собрал все части в один архив и сверил размер и чексум оригинального файла и «воссозданного»:
# воссоздаем архив:
cat archive.tar.gz_* > full_archive.tar.gz
# сверяем размер с оригинальным:
du -sh original.tar.gz
221M original.tar.gz
du -sh full_archive.tar.gz
221M full_archive.tar.gz
# сверяем md5sum
md5sum original.tar.gz
cc157ca6139157a8a9f816e8fbe4390b original.tar.gz
md5sum full_archive.tar.gz
cc157ca6139157a8a9f816e8fbe4390b full_archive.tar.gz
Как мы видим, архив «воссоздан» и готов к распаковке.
Как понять, что делает эта утилита?
На помощь приходит ключ —verbose:
# split archive.tar.gz archive.tar.gz_ -n2 --verbose
creating file 'archive.tar.gz_aa'
creating file 'archive.tar.gz_ab'
# ls -lah archive.tar.gz*
-rw-r--r-- 1 root root 111M янв 16 22:24 archive.tar.gz_aa
-rw-r--r-- 1 root root 111M янв 16 22:24 archive.tar.gz_ab
Как split работает с текстовыми файлами?
По умолчанию эта утилита делит файл создавая новый файл, который содержит 1000 строк. К примеру, у меня есть файл который содержит 11266 строк. Вот на сколько файлов/и как он будет разделен:
# split logfile.log logfile.log_
# wc -l ./logfile.log_*
1000 ./logfile.log_aa
1000 ./logfile.log_ab
1000 ./logfile.log_ac
1000 ./logfile.log_ad
1000 ./logfile.log_ae
1000 ./logfile.log_af
1000 ./logfile.log_ag
1000 ./logfile.log_ah
1000 ./logfile.log_ai
1000 ./logfile.log_aj
1000 ./logfile.log_ak
266 ./logfile.log_al
11266 total
Как мне разделить файл на несколько файлов по 3000 строк?
Тут нам поможет ключ -l 3000:
# split logfile.log logfile.log_ -l 3000
# wc -l ./logfile.log_*
3000 ./logfile.log_aa
3000 ./logfile.log_ab
3000 ./logfile.log_ac
2266 ./logfile.log_ad
11266 total
Как разделить текстовый файл по 300кб не ломая структуру?
При разделении текстового файла по размеру, используя ключ -b файлы делятся на части не сохраняя структуру, из-за чего начало строки может быть в одном файле, а ее конец — в другом. Решить эту проблему можно указав ключ «-C 300KB» (указываем максимальный размер), который разделит файл на части сохраняя структуру.
split -C 300KB ./logfile.log "logfile.log_"
Результат:
# ls -lah logfile.log_*
-rw-r--r-- 1 root root 293K янв 16 23:30 logfile.log_aa
-rw-r--r-- 1 root root 293K янв 16 23:30 logfile.log_ab
-rw-r--r-- 1 root root 95K янв 16 23:30 logfile.log_ac
Как разделить файл на основе определенного контента?
В этом утилита split нам не поможет, но поможет csplit. Возможно о ней будет написана отдельная статья.
Источники, которые я использовал:
https://www.gnu.org/software/coreutils/manual/html_node/split-invocation.html
https://www.linux.com/training-tutorials/split-and-join-targz-file-linux
https://andreyex.ru/linux/komandy-linux-i-komandy-shell/9-poleznyh-primerov-komandy-split-v-linux