Как я могу заставить xargs выполнять команду ровно один раз для каждой заданной строки ввода? Поведение по умолчанию состоит в том, чтобы разбить строки на части и выполнить команду один раз, передавая несколько строк каждому экземпляру.
С http://en.wikipedia.org/wiki/Xargs :
find / path -type f -print0 | XARGS -0 RM
В этом примере команда find передает входные данные xargs с длинным списком имен файлов. Затем xargs разбивает этот список на подсписки и вызывает rm один раз для каждого подсписка. Это более эффективно, чем эта функционально эквивалентная версия:
find / path -type f -exec rm '{}' \;
Я знаю, что у find есть флаг "exec". Я просто привожу иллюстративный пример из другого ресурса.
find /path -type f -delete
будет еще более эффективным :)Ответы:
Следующее будет работать, только если у вас нет пробелов в вводе:
со страницы руководства:
источник
xargs -n 1
как тот, который вы дали, показал «список аргументов слишком длинный».MAX-LINES
он опущен, то по умолчанию он равен 1, поэтому этогоxargs -l
достаточно. Смinfo xargs
.echo "foo bar" | xargs -n1 echo
. следовательно, если вы передадите что-то вроде ls, он не будет хорошо обрабатывать пробелы.-L 1
не отвечает на первоначальный вопрос, и-n 1
делает это только в одной из возможных интерпретаций. Смотрите мой длинный ответ ниже.-L 1
делает. Мне казалось, что OP явно пытался избежать поведения по умолчанию, и, поскольку это было принято, я предполагаю, что был прав. Ваш ответ касается немного другого варианта использования, в котором вы также хотите использовать чанкинг.Мне кажется, что все существующие ответы на этой странице неверны, включая ответ, помеченный как правильный. Это связано с тем, что вопрос сформулирован неоднозначно.
Описание: Если вы хотите выполнить команду «ровно один раз для каждой заданной строки ввода», передав всю строку (без новой строки) команде в виде одного аргумента, то это лучший UNIX-совместимый способ сделать это:
GNU
xargs
может иметь или не иметь полезных расширений, которые позволяют вам покончить с этимtr
, но они недоступны в OS X и других системах UNIX.Теперь для длинного объяснения ...
При использовании xargs необходимо учитывать две проблемы:
Чтобы протестировать поведение xargs, нам нужна утилита, которая показывает, сколько раз он выполняется и сколько аргументов. Я не знаю, есть ли стандартная утилита для этого, но мы можем довольно легко ее кодировать в bash:
Предполагая, что вы сохраните его как
show
в текущем каталоге и сделаете его исполняемым, вот как это работает:Теперь, если исходный вопрос действительно касается пункта 2. выше (как я думаю, после прочтения его несколько раз), и его следует читать так (изменения выделены жирным шрифтом):
тогда ответ
-n 1
.Давайте сравним поведение по умолчанию в xargs, которое разделяет вводные данные вокруг пробела и вызывает команду как можно меньше раз:
и его поведение с
-n 1
:Если, с другой стороны, первоначальный вопрос касался пункта 1. Разделение входных данных и его нужно было читать следующим образом (многие люди, приходящие сюда, думают, что это так, или путают эти две проблемы):
тогда ответ более тонкий.
Можно подумать, что это
-L 1
может помочь, но оказывается, что это не меняет парсинга аргументов. Он выполняет команду только один раз для каждой строки ввода с таким количеством аргументов, сколько было в этой строке ввода:Мало того, но если строка заканчивается пробелом, она добавляется к следующему:
Ясно,
-L
что дело не в том, чтобы изменить способ, которым xargs разделяет входные данные на аргументы.Единственный аргумент, который делает это кроссплатформенным способом (исключая расширения GNU), это то
-0
, что разделяет входные данные вокруг байтов NUL.Тогда это просто вопрос перевода строк в NUL с помощью
tr
:Теперь синтаксический анализ аргумента выглядит хорошо, включая завершающий пробел.
Наконец, если вы объедините эту технику с
-n 1
, вы получите ровно одно выполнение команды на строку ввода, независимо от того, какой у вас ввод, что может быть еще одним способом взглянуть на исходный вопрос (возможно, наиболее интуитивно понятный, учитывая заголовок):источник
-L
выполняет команду один раз для каждой строки ввода (но пробел в конце строки соединяет ее со следующей строкой, и строка все еще разделяется на аргументы в соответствии с пробелами); while-n
выполняет команду один раз для каждого входного аргумента. Если вы посчитаете количество->
в выходных примерах, это число раз, когда скрипт./show
будет выполнен.xargs
может иметь или не иметь полезных расширений, которые позволяют вам покончить сtr
ним, имеет такое очень полезное расширение; fromxargs --help
- -d, --delimiter = элементы CHARACTER во входном потоке разделяются символом CHARACTER, а не пробелом; отключает обработку цитат и обратной косой черты, а также обработку логических EOF-L
.-L
не говорится, сколько раз нужно выполнить скрипт на строку, он говорит, сколько строк входных данных нужно использовать за раз.Если вы хотите выполнить команду для каждой строки (то есть результата)
find
, то для чего вам нужнаxargs
?Пытаться:
find
путь-type f -exec
твоя команда{} \;
где литерал
{}
заменяется именем файла, а литерал\;
необходим для того,find
чтобы знать, что пользовательская команда на этом заканчивается.РЕДАКТИРОВАТЬ:
(после редактирования вашего вопроса уточните, что вы знаете о
-exec
)От
man xargs
:Обратите внимание, что имена файлов, заканчивающиеся пробелами, могут вызвать проблемы, если вы используете
xargs
:Поэтому, если вам не нужен этот
-exec
вариант, лучше использовать-print0
и-0
:источник
-L 1
это простое решение, но оно не работает, если какой-либо из файлов содержит пробелы в них. Это ключевая функция-print0
аргумента find - разделять аргументы символом \ 0 вместо пробела. Вот пример:Лучшее решение - использовать
tr
для преобразования\0
символов новой строки в символы null ( ), а затем использоватьxargs -0
аргумент. Вот пример:Если затем вам нужно ограничить количество вызовов, вы можете использовать
-n 1
аргумент для одного вызова программы для каждого ввода:Это также позволяет вам фильтровать выходные данные find перед преобразованием разрывов в нули.
источник
-L
также состоит в том, что он не допускает множественных аргументов для каждогоxargs
вызова команды.»?Еще одна альтернатива ...
источник
Эти два способа также работают и будут работать для других команд, которые не используют find!
пример использования:
удалит все файлы pyc в этом каталоге, даже если файлы pyc содержат пробелы.
источник
это все, что тебе нужно.
источник
Следующая команда найдет все файлы (-type f)
/path
и скопирует ихcp
в текущую папку. Обратите внимание на использование if-I %
для указания символа-заполнителя вcp
командной строке, чтобы аргументы можно было размещать после имени файла.find /path -type f -print0 | xargs -0 -I % cp % .
Протестировано с помощью xargs (GNU findutils) 4.4.0
источник
Вы можете ограничить количество строк или аргументов (если между аргументами есть пробелы), используя флаги --max-lines или --max-args соответственно.
источник
Кажется, у меня недостаточно репутации, чтобы добавить комментарий к ответу Тобиа выше , поэтому я добавляю этот «ответ», чтобы помочь тем из нас, кто хочет экспериментировать с
xargs
аналогичным способом на платформах Windows.Вот пакетный файл Windows, который делает то же самое, что и быстро закодированный скрипт «show» Тобиа:
источник
Ответы @Draemon кажутся правильными с «-0» даже с пробелом в файле.
Я пробовал команду xargs и обнаружил, что «-0» отлично работает с «-L». обрабатываются даже пробелы (если ввод был завершен нулем). Ниже приведен пример:
Следующее разделит пустые значения и выполнит команду для каждого аргумента в списке:
так
-L1
будет выполнять аргумент для каждого символа с нулевым символом в конце, если используется с «-0». Чтобы увидеть разницу попробуйте:даже это будет выполнено один раз:
Команда будет выполнена один раз, так как «-L» теперь не разбивается на нулевой байт. вам нужно указать и "-0", и "-L" для работы.
источник
В вашем примере смысл передачи вывода find в xargs заключается в том, что стандартное поведение параметра find -exec состоит в том, чтобы выполнить команду один раз для каждого найденного файла. Если вы используете find и вам нужно его стандартное поведение, тогда ответ прост - не используйте xargs для начала.
источник
find
, и поэтому они не предпочитают этот-exec
вариант.выполнить задачу ant ant clean-all для каждого build.xml в текущей или вложенной папке.
источник
ant
установили.