Чому не всі файли стискаються та як покращити рішення


8

У мене папка з приблизно 20K файлами. Файли називаються відповідно до шаблону xy_{\d1,5}_{\d4}\.abc, наприклад xy_12345_1234.abc. Я хотів стиснути перші 10K з них за допомогою цієї команди:

ls | sort -n -k1.4,1.9 | head -n10000 | xargs tar -czf xy_0_10000.tar.gz

однак отриманий файл мав лише близько 2K файлів всередині.

ls | sort -n -k1.4,1.9 | head -n10000 | wc -l однак повертає 10000, як і очікувалося.

Мені здається, я тут розумію щось базове ...

Я використовую zsh 5.0.2 для Linux Mint 17.1, GNU tar 1.27.1

Редагувати:

розгортання, як запропонував @Archemar, звучить дуже правдоподібно, остання вилка перезаписує отриманий файл - файл містить "хвіст" файлів - від 7773 до 9999 .

результат xargs --show-limit: Your environment variables take up 3973 bytes POSIX upper limit on argument length (this system): 2091131 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2087158 Size of command buffer we are actually using: 131072

заміна -cз -rабо -uне працює в моєму випадку. Повідомлення про помилку булоtar: Cannot update compressed archives

використання обох -rі -uнедійсне і не працює зtar: You may not specify more than one '-Acdtrux', '--delete' or '--test-label' option

заміна -cна, -aздається, також недійсна і не вдається з тим самим, tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' optionsхоча я не визнаю проблему azfі, Acdtruxздається, суперечить мені.

EDIT 2:

-T виглядає як хороший спосіб, я також знайшов приклад тут .

Однак коли я намагаюся

ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T - я отримав tar: option requires an argument -- 'T'

ну, можливо, назви файлів не досягають дьогтю? Але це схоже на них, тому що коли я страчу

ls | sort -n -k1.4,1.9 | head -n10000 | tar --null -czf xy_0_10000.tar.gz -T - я отримав tar: xy_0_.ab\nxy_1_...<the rest of filenames separated by literal \n>...998.ab Cannot stat: File name too long

То чому тар не бачить назви файлів?


і якщо ви спробуйте замість c, в команді tar?
Олів'є Дулак

5
Відповідно: Неls
розбирайте

1
Файл OP не має хитрих назв.
Архемар

@ 8bittree - також загальна порада щодо надійних сценаріїв оболонок, так. але що ви пропонуєте замість цього працювати зі списками файлів із звичайними одноразовими лінійками?
костя

1
Я використовував би @kostja find, який має -print0можливість використовувати нульовий байт як роздільник замість нового рядка. sortможе впоратися з цим -zпрапором. head, на жаль, не вдається зрозуміти нульові байтові обмежувачі, але ця відповідь має рішення за допомогою trswap \nі \0до, і після head. tarмає --null -T -читати імена файлів з нульовим обмеженням stdin.
8bittree

Відповіді:


12

ви досягли ліміту xargs?

xargs --show-limit

спробуйте:

  • створити фіктивний .tgzфайлtar czf xy_0_10000.tar.gz /hello/world
  • замінити -czfна -Azf

коли xarg вдарив свою межу, він відкине команду, тому команда, якою ви ultimatly біг, була

  tar czf xy_0_10000.tar.gz file1 file2 .... file666
  tar czf xy_0_10000.tar.gz file667 file668 ... file1203
  tar czf xy_0_10000.tar.gz file1024 ... file2000

оскільки кожен дьоготь понад попередній, ви можете отримати лише останній tar cзапуск.

Редагувати:

1) згідно man tarз unbuntu, -aі -r здається еквівалентним додаванням робиться (або) -A, --catenate, --concatenate

2) zip(не gzip) можна використовувати для додавання файлу, можливо, gzip варіант зробить трюк. (використання | xargs zip -qr xy_0_0000.zip, це призведе до поштового файлу, але не .tar.gz)

3) використовувати рішення @ rsanchez
Важливо правильно додати опцію tar, спробуйте

ls | sort -n -k1.4,1.9 | head -n10000 |tar -czf xy_0_10000.tar.gz -T -

де - -T -середній варіант використання -Tта використання -в якості аргументу -T(ви могли б створити список файлів /tmp/foo.lst, а потім використовувати -T /tmp/foo.lst)


міг (= додати) замість c (= створити / перезаписати) обійти це обмеження?
Олів'є Дулак

@OlivierDulac ( Увага: це чиста здогадка ) Це, ймовірно, не вирішиться, оскільки tar не може створити порожні файли. Ви можете спочатку стиснути порожню папку та використовувати її a (add)для додавання файлів у файл tar. Потім ви можете відкрити тар і видалити папку (використовуючи 7zip або щось подібне)
Ісмаель Мігель

@ismaelmiguel: Я впевнений, що він із задоволенням створить файл. якщо ні, то просто:touch xy_0_10000.tar.gz && { _the full command here_ ; }
Олів'є Дулак

1
@OlivierDulac Це буде недійсний .gzфайл.
Ісмаїл Мігель

Всі манжети, які я бачу з manpages.ubuntu.com/manpages/vivid/en/man1/tar.1.html (15.04) до точного (12.04), -rдодають, але -aавтоматично стискають, що не є рівнозначним. І -rzне працює: zipможе додати до вже існуючого архіву, оскільки каталог не стискається, а tarпри стисненні стискає метадані разом із даними. Ви можете tar -rкусочно скластись у нестиснений архів, а потім зібрати результат. Або ...
dave_thompson_085

12

У цьому немає потреби xargs. Якщо ви відразу даєте tarв -T -опції він буде читати імена файлів зі стандартного вводу.

Наприклад:

... | tar -T - -czf xy_0_10000.tar.gz

Я, здається, використовує параметр неправильно, не можу змусити його працювати з трубою. Намагався ...| tar Tczf xy_..., ...| tar Tcz -f xy_... ...| tar -czf xy_... -T і кілька інших перестановок, але я отримую тільки tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options, tar: -f: Cannot stat: No such file or directoryякщо використовується -fокремо від інших варіантів і tar: option requires an argument -- 'T'. Не могли б ви додати приклад використання?
костя

Приклад @kostja додано.
rsanchez

Велике спасибі, rsanchez. Не впевнений, чому варіант з -T -в кінці списку tarопцій не працював, але ваш приклад так і зробив. На жаль, моє запитання насправді мало дві частини - джерело помилки та можливе вдосконалення. У той час як Ви відмовились від останнього, Архемар відзначився першим і майже мав право останнього. Я не впевнений, яку з ваших відповідей прийняти, оскільки вони обоє були явно корисними.
костя

1

Я хочу доповнити дві інші відповіді рішенням zsh , яке ні аналізує ls , ні потрібні xargs . Однак я зараз не впевнений, якщо це також страждає від обмеження довжини командного рядка.

  1. Визначте функцію, яка генерує бажаний ключ сортування, змінивши $REPLY.

    sortkey() { REPLY=${REPLY[4,9]} }

    Це еквівалентно вашому sort -n -k1.4,1.9

  2. Створіть масив $filesз іменами файлів, відсортованими за вказаною вище функцією:

    files=(*(o+sortkey))

    Це еквівалентно ls | sort -n -k1.4,1.9

  3. Поверніть перші 10 000 файлів за допомогою

    ${files[0,9999]}

    Це еквівалентно ls | sort -n -k1.4,1.9 | head -n10000

Отже, у всьому цьому слід зробити трюк:

sortkey() { REPLY=${REPLY[4,9]} }
files=(*(o+sortkey))
tar -czf xy_0_10000.tar.gz ${files[0,9999]}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.