Как правильно использовать «xargs», если список аргументов слишком длинный - PullRequest
7 голосов
/ 26 марта 2009

Может кто-нибудь дать мне пример использования xargs в приведенной ниже операции?

tar c $dir/temp/*.parse\
    | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma

Я получаю сообщение об ошибке от bash " / bin / tar: список аргументов слишком длинный "

В частности, я пытаюсь выполнить сжатие LZMA для 4500 файлов; так что это не удивительно. Я просто не знаю, как изменить вышеупомянутое, чтобы использовать xargs и избавиться от ошибки! Спасибо.

Ответы [ 5 ]

11 голосов
/ 26 марта 2009

Расширение ответа CristopheDs и предполагается, что вы используете bash:

tar c --files-from <(find $dir/temp -maxdepth 1 -name "*.parse") | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma

Причина, по которой xargs вам здесь не помогает, заключается в том, что она будет выполнять несколько вызовов, пока не будут использованы все аргументы. Это вам здесь не поможет, так как это создаст несколько архивов tar, которые вам не нужны.

10 голосов
/ 26 марта 2009

В качестве примечания:

Всегда, всегда избегайте xargs (1). Это сломанный инструмент, и он полезен только удаленно, если вы используете его с опцией -0. Даже тогда почти всегда лучше использовать опцию find (1) -exec или простой цикл for или while.

Почему xargs такой плохой? Во-первых, он разбивает входные данные на пробелы, то есть все ваши имена файлов, которые содержат пробелы, вызовут хаос. Во-вторых, пытается быть умным, а анализирует кавычки для вас. Это приводит только к большему количеству головной боли, поскольку вы используете его для имен файлов, которые содержат кавычки как часть имени файла, такие как песни: " Я не хочу пропустить вещь .mp3 ". Это только заставит xargs вырваться и проклинать вас за то, что вы плохо процитировали его ввод. Нет, вы этого не сделали: нужно просто узнать, что кавычки не принадлежат входным данным, они принадлежат сценариям оболочки , и xargs не имеет никакого дела, пытаясь их проанализировать.

Имейте в виду, xargs (1) не разбивает пробелы и не разбирает кавычки, когда вы передаете ему -0. Это делает правильную вещь , которая использует NULL-байты для разделения имен файлов. Но это означает, что вам нужно дать ему входные данные, которые используют имена файлов, разделенные байтами, равными NULL (например, " find -foo -print0 "). Что возвращает нас к следующему: лучше всего использовать find -exec: " find -foo -exec bar {} + ".

4 голосов
/ 26 марта 2009

Возможно, вы хотите что-то подобное?

find $dir/temp/ -name '*.parse' -print0 | tar --null -T - -c | lzma -9 > $dir/backup/$(date '+%Y-%m-%d')-archive.tar.lzma
4 голосов
/ 26 марта 2009

Используйте find, чтобы передать «нужные» имена файлов во временный файл, а затем используйте tar с параметром командной строки '-–files-from'.

Edit:

или передайте их напрямую друг другу, чтобы избежать временного файла.

Итак: используйте find, чтобы получить список желаемых имен файлов | tar ... --files-from

0 голосов
/ 26 марта 2009

Поскольку вы работаете в Linux, у вас есть GNU tar, и вы можете использовать опцию '-F -' или '--files-from' для чтения имен файлов.

Однако вы также можете использовать:

- use-compress-program = "lzma -9"

, чтобы указать используемую программу сжатия и просто дать имя файла сжатия в качестве целевого файла для команды 'tar'.

Это было необходимо для сжатия 'bzip2' до добавления опции '-j'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...