У меня есть один файл tar, содержащий около 19 миллионов файлов (без папок)
0000107b869682826003b04a40e6394.txt
00029237482s8923789423ud8923892.txt
2c002y8378723887292377a79237649.txt
f598238209237408238742308374038.txt
как мне распаковать все файлы так, чтобы они отображались в подкаталогах, названных по первым четырем символам файлов. Итак, для приведенного выше примера он создаст 0000
, 2c02
, а также f599
каталоги, и в каждом будут следующие файлы.
0000 000107b869682826003b04a40e6394.txt
0002 0029237482s8923789423ud8923892.txt
2c022c002y8378723887292377a79237649.txt
f598f598238209237408238742308374038.txt
Я уже пробовал создать сценарий, который просматривает файлы в tar-файле, создает каталог, извлекает этот файл из tar и помещает его в каталог. Это работает для небольшого количества файлов, но когда в tar их миллионы, извлечение занимает очень много времени.
2 ответа
С GNU tar
И его s
команда с синтаксисом из sed
. Я перешел с s///
к s|||
.
tar -xvf file.tar --transform 's|(....).*|1/&|' --show-transformed-names
Я создал тестовый тарбол, без каталогов:
pg@TREX:~/test$ tar -tvf test.tar | rev | cut -c -8 | rev
0001.txt
0002.txt
0003.txt
0004.txt
0005.txt
0011.txt
0012.txt
0013.txt
0014.txt
0015.txt
0021.txt
0022.txt
0023.txt
0024.txt
0025.txt
Я запускаю этот скрипт (tartest.sh):
#!/bin/bash
tar -xf tarfile.tar
i=$(ls *.txt | cut -c -3 | sort | uniq)
echo "$i" >> directory_list
mkdir $i
while read line; do mv $line*.txt $line/; done < directory_list
Результат:
pg@TREX:~/test$ tree
.
├── 000
│ ├── 0001.txt
│ ├── 0002.txt
│ ├── 0003.txt
│ ├── 0004.txt
│ └── 0005.txt
├── 001
│ ├── 0011.txt
│ ├── 0012.txt
│ ├── 0013.txt
│ ├── 0014.txt
│ └── 0015.txt
├── 002
│ ├── 0021.txt
│ ├── 0022.txt
│ ├── 0023.txt
│ ├── 0024.txt
│ └── 0025.txt
├── directory_list
├── tartest.sh
└── test.tar
Я уверен, что это займет немного времени с файлами 19mil, и я уверен, что существуют более элегантные решения … но, похоже, они делают то, что вы просили 🙂
- 1
Это могло произойти с 19 миллионами файлов:
ls *.txt
— Сайрус
12 часов назад
Да, если все файлы не имеют расширения .txt, как описано в вопросе OP: s. Однако он должен работать без расширения, создавая директорию «tar» и перемещая туда сам файл tar — вместе с любым другим файлом, начинающимся с этих символов 🙂 Или вы видите проблему с использованием ls в первую очередь? В любом случае, я предпочитаю ваш однострочник — я даже не знал, что sed можно так связать с tar 🙂
— Пилигрим69
12 часов назад
Я предполагаю, что если
bash
заменяет*.txt
с 19 миллионами имен файлов, чтоbash
затем выведетargument list too long
.— Сайрус
12 часов назад
О, это вообще не приходило мне в голову. И в соответствии с наследием мистера Мерфи, это должно было произойти с файлом 18 699 453 :-D.
— Пилигрим69
12 часов назад
- 1
Вы можете просто заменить его на
ls | egrep '.txt$' | ...
— слебетман
4 часа назад
LOL — действительно более элегантное решение 😀 Но если говорить о файлах 19mil, это все равно займет время 🙂
— Пилигрим69
13 часов назад