Витяг .gz файлів, що містяться в папці


13

У мене папка, яка містить приблизно 320116 файли .pdb.gz. Хочеться розпакувати їх усіх. Якщо я використовую gunzip * .gz, це дає мені помилку, тобто список аргументів занадто довгий. Папка близько 2 Гб. Будь ласка, дайте мені відповідну пропозицію.


Якщо вам доведеться довго працювати над цією структурою каталогу, розділіть цей каталог на багато. Наприклад, на основі часу зміни файлів або назви файлів.
дан

Так, мені доводиться довго працювати. їх витягнули зараз, я хочу поділити їх і класифікувати на три папки на основі їх імен. Чи існує сценарій оболонки для цього?
Лілі Шарптон

Я пропоную вам шукати подібні запитання там. Якщо ви не знайдете потрібного, задайте нове власне запитання.
дан

Відповіді:


25
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +надасть gunzipбагато, але не занадто багато імен файлів у своєму командному рядку. Це більш ефективно, ніж -exec gunzip {} \;це запускає новий gunzipпроцес для кожного файлу.


3
Один find, менше gunzip!
дан

2
Зауважте, що "+" є GNUism і тому не працюватиме в системах, що не належать до GNU, як * BSD.
Відновіть Моніку - М. Шредер

3
Пізніші версії BSD findдозволяють позначити "+". Дивіться, наприклад, на findсторінці керівництва BSD 10.1 . Також стосується OS X (10.9 і принаймні пізніше, можливо, і раніше).
плазма

7

Щоразу, коли ви отримуєте помилки "списку аргументів", ви можете обійти його, викликаючи потрібну команду кілька разів, кожен раз із підмножиною аргументів, які ви хочете використовувати. xargsце інструмент, який допоможе вам зробити це автоматично.

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip

хіба це не має такої ж неефективності, як -execdir gunzip "{}" \;тобто xargs буде викликати gunzip окремо для кожного файлу? Це моє читання сторінки людини.
gogoud

5
Ні, xargsбуде заповнено стільки імен файлів, скільки вміститься в gunzipкомандному рядку. Спробуй це! echo a b c d e f | xargs echoлише echoодин раз викликає всі 6 аргументів, тож ви бачите один рядок виводу (хоч і непотрібна команда для виконання !!!!), хоча якщо ви змушуєте xargsподавати до 3 аргументів за виклик команди, використовуючи, echo a b c d e f | xargs -n 3 echoтоді ви отримуєте 2 рядки виводу .
Целада

4
Ще одна перевага використання xargsполягає в тому, що за допомогою цього -Pпараметра ви можете запускати кілька gunzipпроцесів паралельно, які (залежно від точних параметрів вашої системи) можуть йти швидше.
psmears

дякую за вказівник на -P, @psmears. Тепер я теж щось навчився!
Целада

1

Я думаю, що це має спрацювати, воно передає шлях / ім’я кожного файлу окремо до gunzip для обробки:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;

1
Це виконає gunzip один раз на файл. Дивіться відповідь John1024 дещо іншим способом, який дозволяє уникнути цієї неефективності.
Селада

@Celada Це було навмисно; я побоювався, що використання + може знову призвести до повідомлення про помилку через перевантаження gunzip. Якщо метод John1024 працює, він технічно більш ефективний, але мій повинен працювати, якщо його немає.
gogoud

1
findз +та xargsє чітко дизайнером, маючи на увазі саме це питання. Вони завжди будуть надавати стільки аргументів, скільки можуть, при цьому не перевищуючи ліміт операційної системи. Тому що, до речі, він є ценз роботи системи, нічого спільного з gunzip.
Целада

1
@Celada ок, дякую за цю інформацію, тож, мабуть, з '+' gunzip можна буде викликати не один раз, але менше ніж 320 000 разів?
gogoud

1
правильно‍‍‍‍‍‍‍.
Целада

1

Спробуйте таким чином:

find . -name '*.gz' -exec gunzip {} \;

3
Це буде виконуватися gunzipодин раз на файл. Дивіться відповідь John1024 дещо іншим способом, який дозволяє уникнути цієї неефективності.
Селада

Не забудьте уникнути * in * .gz ...
user253751

1

Якщо у вас багатоядерна машина, ви, ймовірно, побачите, що використання gunzipне збільшить можливості вашої машини. Для цього вам потрібно запустити кілька gunzips паралельно. Щоб відстежувати, що робиться, в якому терміналі вручну є громіздким, але ви можете легко зробити це за допомогою паралелі GNU:

find . -name "*.gz" | parallel -X gunzip {}

1
Невже це не вдасться, оскільки список аргументів parallelзанадто довгий?
користувач253751

@immibis Так, я забув початкову проблему, оновлю свій пост
Ентон

Не все-таки це не вдасться, оскільки список аргументів findзанадто довгий?
користувач253751

1
так, але ви передаєте всі імена файлів у findкомандному рядку.
користувач253751

Здається, це не сприятливий день для відповіді на запитання, я забув цитувати цей аргумент-name
Антон

-1

Для цього зайве використовувати find, оскільки ви не згадали про підпапки. Що вам потрібно зробити:

for f in *.gz;do gunzip $f;done

4
Вам це потрібно, findякщо ви не хочете нерестувати 320116 gunzipпроцеси, як це робить цикл.
Джон У. Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.