Пример опции -x xargs в действии - PullRequest
4 голосов
/ 12 июня 2010

GNU xargs имеет опцию '-x'.Страница man говорит:

-x Выйти, если размер (см. Параметр -s) превышен.

Но xargs, кажется, не волнует, если -x установлено или нет.Мне не удалось привести пример, в котором -x вообще имеет какой-либо эффект.

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

Ответы [ 3 ]

4 голосов
/ 12 июня 2010

Вы должны установить размер, чтобы проверить, превышает ли он его.

$ echo -e "12\n1234"
12
1234
$ echo -e "12\n1234" | xargs echo
12 1234
$ echo -e "12\n1234" | xargs  -x echo        # no effect
12 1234
$ echo -e "12\n1234\n13" | xargs -s 8 echo   # process valid args until an error occurs
xargs: argument line too long
12
$ echo -e "12\n1234" | xargs -s 8 -x echo    # error and exit
xargs: argument line too long
1 голос
/ 28 января 2016

Я до сих пор не могу объяснить, почему это дает 1 - 11:

(seq 11; echo -e "1234111";seq 12 15) | xargs -s 11 echo

, но это дает 1 - 9:

(seq 11; echo -e "1234111";seq 12 15) | xargs -s 11 -x echo

Будет -x всегда только даватьразница в одну строку (а именно строку, которая была бы слишком длинной)?

Это, конечно, зависит от типа xargs, который вы используете, но от распространенных GNU findutils 'xargs (который вполне может быть тем, что у вас есть) имеет именно такое поведение, нарушая принцип наименьшего удивления: он накапливает командную строку в памяти, многократно читая следующий элемент ввода и добавляя его в существующую командную строку, пока не выполнитвписаться в длину строки… Теперь он проверяет, поместится ли прочитанный элемент в строку в качестве единственного аргумента (как в случае с echo 1234111 в вашем примере):

      if (p >= endbuf)
        {
          exec_if_possible ();
          error (EXIT_FAILURE, 0, _("argument line too long"));
        }

(приведенный выше код находится в конце функции read_line() в findutils-4.6.0 / xargs / xargs.c, почти так же, как в findutils-4.4.2)

static void
exec_if_possible (void)
{
  if (bc_ctl.replace_pat || initial_args ||
      bc_state.cmd_argc == bc_ctl.initial_argc || bc_ctl.exit_if_size_exceeded)
    return;
  bc_do_exec (&bc_ctl, &bc_state);
}

Вот где опция -x (соответствует bc_ctl.exit_if_size_exceeded) имеет значение - с -x, exec_if_possible() просто return с без bc_do_exec() без уже накопленной правильно сформированной команды (echo 10 11 в вашем примере).Затем после return ing, функция error() выходит из программы xargs.

Я ожидал, что 12 - 15 будет в одном из них.

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

0 голосов
/ 29 января 2016

ТЛ; др

  • Использование -x имеет смысл только с -n <argumentCount>: <argumentCount> аргументами, если они доступны, должен соответствовать одной командной строке , основанный либо на неявном максимуме подсчета байтов, либо на явно заданной опции -s <byteCount+1>; если нет, xargs выходит с ошибкой.
    Без -x будет создана командная строка с меньшим аргументами, и не возникнет ошибка - если не подходит даже единственный аргумент - см. Следующий пункт .

    • Обратите внимание, что логика -x неявно применяется к опциям -L <lineCount> и -I <placeHolder>.
    • Предупреждение : Начиная с OSX 10.11.3 и PC-BSD 10.1, комбинация -x и -n представляется прерывистой в BSD реализация xargs - см. Ниже.
  • Без -n НЕТ причины использовать -x, потому что обе xargs реализации всегда завершают работу с ошибкой при обнаружении единственный аргумент, который приведет к слишком длинной команде для общего предела размера байта (опять же, либо подразумеваемый, либо указанный с помощью -s <byteCount+1>).

    • GNU xargs: -x без -n поверхностей ошибка (с версии 4.2.2), как раскопано в Печальный ответ Армали .
    • BSD xargs: -x без -n является синтаксически не поддерживается .
    • Простой пример, который показывает для обеих реализаций, что даже без -x один слишком длинный аргумент вызывает ошибку:
      • $ echo 1 10 | xargs -s 7 echo # max. command length is 6 (7 - 1) bytes 1 # ok: 'echo 1' is 6 bytes xargs: argument line too long # 'echo 10' is too long

Следующие GNU xargs примеры:

  • указывает, что следует использовать последовательность из 2 аргументов, если таковые имеются, следует , , если возможно ( без -x) или , должны использоваться ( с -x) для каждого экземпляра команды: -n 2
  • ограничить каждую команду не более 8 (9 - 1) байтов: -s 9

Примечание: С BSD xargs приведенный ниже пример no -x работает так же, а пример -x должен работает, но не работает с версией xargs, найденной в OSX 10.11.3 и PC-BSD 10.1: при указании -x указанное значение <argumentCount> в -n <argumentCount> игнорируется, а xargs ведет себя так, как будто -n 1 было указано.

# NO -x: Use 2 arguments *if possible*.
$ echo -e "1 2 3 4a 5 6" | xargs -n 2 -s 9  echo
1 2
3    # 'echo 3 4a' is more than 8 (9 - 1) bytes -> '3' is used *alone*
4a   # 'echo 4a 5' also doesn't fit -> '4a' is also used alone.
5 6

# WITH -x: *Must* use 2 arguments (if available); *fail* otherwise.
$ echo -e "1 2 3 4a 5 6" | xargs -n 2 -s 9 -x echo
xargs: argument list too long  # 'echo 3 4a' is too long; cannot use 2 arguments -> error
1 2

Обратите внимание, как странно печатается сообщение об ошибке перед последней успешно выполненной командой; возможно, это связано с вышеупомянутой ошибкой, поэтому ответ Армали может дать объяснение.

...