LINUX.ORG.RU
решено ФорумTalks

Поиск, группировка по имени и сжатие файлов

 , , ,


0

2

В каталоге есть файлы, имеющие общее начало названия (если конкретно, то timestamp). Задача сгруппировать эти файлы, например, по первым 6 символам и сжать в архив с названием из этих 6 символов. Все файлы находятся на одном уровне и должны паковаться без относительных путей. У меня получилось следующее:

for i in $(ls -1 $SRC | cut -c 1-6 | uniq); do
  find $SRC -name "$i*" -printf "%f\n" | tar -zcf $TARGET/$i.tgz -C $SRC --files-from -
done

Можно ли решить эту задачу менее костыльным способом? Какие предложения по улучшению и оптимизации?


Если есть гарантия что
- среди файлов не каталогов
- в первых 6 символах нет пробелов
то вроде норм.

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

Хотя, параметры tar проверь. Я с tar мало работал, но смущает, что ты ему передаешь -C $SRC , а в списке файлов фигурирует полное имя файла с путями. Ну, то есть ты передаешь -C ./tmp , а потом из stdin приходит ./tmp/file1 . Оно нормально отработает?

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

в первых 6 символах нет пробелов

Это файлы писем, пробелов быть не может, т.к. первые 10 символов гарантированно timestamp

среди файлов нет каталогов

Каталогов нет, но с ними можно справиться через -type f

из stdin приходит ./tmp/file1

Не придёт, т.к. -printf «%f\n» вернёт только имя файла. Вообще можно было бы решить вопрос через tar --include=«'$i*'», но мой tar (GNU tar) 1.26 инклуд не понимает.

ivn86
() автор топика

если файлов много (ну там сотни тыщь) то лучше использовать связку cpio.

find $SRC -name "$i*" | cpio -ov --format=ustar | gzip > $TARGET/$i.tar.gz
vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 1)
Ответ на: zsh. начало. от zolden

zsh. начало.

Красивое решение, но работает только со сменой рабочего каталога (без этого рушится вся красота $file[0,6])

ivn86
() автор топика
Ответ на: zsh. начало. от zolden

В Вашем примере есть проблема со списком внутри списка — первый формируется генератором for, второй маской $file[0,6]* в результате чего tar пакует одни и те же файлы несколько раз:

for file in *(.);tar -avcf /tmp/$file[0,2].tgz $file[0,2]*
111.txt
112.txt
113.txt
114.txt
111.txt
112.txt
113.txt
114.txt
111.txt
112.txt
113.txt
114.txt
111.txt
112.txt
113.txt
114.txt
120.txt
121.txt
120.txt
121.txt
221.txt
222.txt
221.txt
222.txt

У меня тут для примера файлы [111.txt 112.txt 113.txt 114.txt 120.txt 121.txt 221.txt 222.txt] с группировкой по первым двум символам.

Следующий Ваш пример не работает, т.к. tar ищет файлы в текущем каталоге, не находит (потому что они в каталоге $SRC) и падает с ошибкой:

zsh: no matches found: 11*
zsh: no matches found: 11*
zsh: no matches found: 11*
zsh: no matches found: 11*
zsh: no matches found: 12*
zsh: no matches found: 12*
zsh: no matches found: 22*
zsh: no matches found: 22*
ivn86
() автор топика
Ответ на: комментарий от ivn86

в результате чего tar пакует одни и те же файлы несколько раз

это тебе домашнее задание - какой ключ говорит tar'у чтобы не паковал повторно

Следующий Ваш пример не работает, т.к. tar ищет файлы в текущем каталоге

и с этим ты знаешь как разобраться, я в тебя верю

zolden ★★★★★
()

Можно ли решить эту задачу менее костыльным способом?

Если ты используешь BASH - то это уже костыль

Siado ★★★★★
()

Кошмар какой, а нельзя взять python, java или еще что-нибудь человеко-читаемое и написать по-нормальному?

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

а нельзя взять python, java или еще что-нибудь человеко-читаемое

Вам — всё можно. :) Хоть ассемблер. Берите, пишите, предлагайте своё решение. Я предложил своё. Возможно оно не оптимально, но оно работает, 30K файлов раскиданы по 700 архивам, задача решена, все довольны.

написать по-нормальному?

Вменяемая задача, которая решается группировкой системных вызовов в общем цикле языка системной оболочки — ИМХО это нормально. А вот тянуть для этого JRE на сервер — ИМХО это НЕ нормально.

ivn86
() автор топика

write-only однострочник

find . -name \*.txt -exec bash -c 'P="{}"; T="${P:0:4}.tar" ; [ -f "$T" ] && tar -r -f "${T}" "${P}" || tar -cf "${T}" "${P}" '  \;

maloi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.