Как распаковать несколько файлов в несколько подкаталогов в зависимости от имени файла

У меня есть один файл tar, содержащий около 19 миллионов файлов (без папок)

0000107b869682826003b04a40e6394.txt
00029237482s8923789423ud8923892.txt
2c002y8378723887292377a79237649.txt
f598238209237408238742308374038.txt

как мне распаковать все файлы так, чтобы они отображались в подкаталогах, названных по первым четырем символам файлов. Итак, для приведенного выше примера он создаст 0000, 2c02, а также f599 каталоги, и в каждом будут следующие файлы.

0000000107b869682826003b04a40e6394.txt
00020029237482s8923789423ud8923892.txt
2c022c002y8378723887292377a79237649.txt
f598f598238209237408238742308374038.txt

Я уже пробовал создать сценарий, который просматривает файлы в tar-файле, создает каталог, извлекает этот файл из tar и помещает его в каталог. Это работает для небольшого количества файлов, но когда в tar их миллионы, извлечение занимает очень много времени.

2 ответа
2

С GNU tar И его s команда с синтаксисом из sed. Я перешел с s/// к s|||.

tar -xvf file.tar --transform 's|(....).*|1/&|' --show-transformed-names

  • LOL — действительно более элегантное решение 😀 Но если говорить о файлах 19mil, это все равно займет время 🙂

    — Пилигрим69

    13 часов назад

Я создал тестовый тарбол, без каталогов:

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 часа назад

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *