8

У меня есть папка с около 20K файлов. Файлы именуются в соответствии с шаблоном xy_{\d1,5}_{\d4}\.abc 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 однако 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 кажутся мне несвязанными .

РЕДАКТИРОВАТЬ 2:

-Т выглядит хорошим способом, я также нашел пример здесь.

Однако, когда я пытаюсь

ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T - я получаю tar: option requires an argument -- 'T'

ну, возможно, имена файлов не доходят до tar? Но похоже, что они делают, потому что, когда я выполняю

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

Так почему tar не видит имена файлов?

3 ответа3

12

Там нет необходимости для xargs . Если вы прямо дадите tar опцию -T - она будет читать имена файлов из стандартного ввода.

Например:

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

Вы достигли предела XARGS?

xargs --show-limit

пытаться :

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

когда xarg достигнет своего предела, он выполнит команду fork, поэтому команда, которую вы запустили ультимативно, была

  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, вы можете получить только последний запуск tar c .

Редактировать:

1) в соответствии с man tar в unbuntu, -a и -r кажутся эквивалентными, добавление выполняется (либо) -A, --catenate, --concatenate

2) zip (не gzip) можно использовать для добавления файла, возможно, опция gzip поможет. (используйте | xargs zip -qr xy_0_0000.zip , это приведет к 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 )

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]}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .