Linux find and xargs

Команда Xargs для начинающих с примерами

Оригинал: Linux Xargs Command with Examples
Автор: linuxize
Дата публикации: 21 декабря 2019 года
Перевод: А. Кривошей
Дата перевода: январь 2020 г.

Утилита xargs позволяет создавать и выполнять команды из стандартного ввода.

Xargs обычно используется в сочетании с другими командами через конвейер. Использование xargs позволяет вам предоставлять стандартный ввод в качестве аргументов утилит командной строки, таких как mkdir и rm.

В этом руководстве мы рассмотрим основы использования команды xargs.

Использование команды xargs

Xargs читает аргументы из стандартного ввода, разделенные пробелами или символами новой строки, и выполняет указанную команду, используя входные данные в качестве аргументов команды. Если команда не указана, по умолчанию используется /bin/echo.

Синтаксис команды xargs выглядит следующим образом:

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

В приведенном выше примере мы передаем стандартный ввод в xargs, и для каждого аргумента запускается команда touch, создавая три файла. Это то же самое, как если бы вы запустили:

Как просмотреть команду и запросить подтверждение пользователя

Чтобы вывести команду на терминал перед ее выполнением, используйте опцию -t (—verbose):

Если вы хотите получить подтверждение выполнения команды, используйте параметр -p (—interactive):

Введите y или Y, чтобы подтвердить и выполнить команду:

Этот ключ полезен при выполнении потенциально опасных команд.

Как ограничить количество аргументов

По умолчанию количество аргументов, передаваемых команде, определяется системным лимитом.

Опция -n (—max-args) указывает количество аргументов, передаваемых данной команде. Xargs будет запускать указанную команду столько раз, сколько необходимо, пока не будут исчерпаны все аргументы.

В следующем примере количество аргументов, считываемых из стандартного ввода, ограничено 1.

Как вы можете видеть из подробного вывода ниже, команда touch выполняется отдельно для каждого аргумента:

Как запустить несколько команд

Чтобы запустить несколько команд с xargs, используйте опцию -I. Она работает путем определения replace-str после ключа -I, а затем все вхождения replace-str заменяются аргументом, переданным в xargs.

В следующем примере xargs будут запущены две команды, сначала она создаст файлы с помощью touch, а затем выведет список файлов с помощью команды ls:

Типичным выбором для replace-str является %, однако вы можете использовать другой заполнитель, например ARGS:

Как указать разделитель

Используйте параметр -d (—delimiter), чтобы задать пользовательский разделитель, который может быть либо отдельным символом, либо escape-последовательностью, начинающейся с \.

В следующем пример мы используем «;» в качестве разделителя:

Как читать элементы из файла

Команда xargs также может читать элементы из файла вместо стандартного ввода. Для этого используйте параметр -a (—arg-file), за которым следует имя файла.

В следующем примере команда xargs будет читать файл ips.txt и пинговать каждый IP-адрес.

Мы также используем опцию -L 1, которая указывает xargs читать по одной строке за раз. Если эта опция не указана, xargs передает все IP-адреса одной команде ping.

Использование xargs с find

xargs чаще всего используется в сочетании с командой find. Вы можете использовать find для поиска определенных файлов, а затем использовать xargs для выполнения операций с этими файлами.

Чтобы избежать проблем с именами файлов, которые содержат символы новой строки или другие специальные символы, всегда используйте параметр find -print0, который заставит find печатать полное имя файла, за которым следует нулевой символ. Этот вывод может быть правильно интерпретирован xargs с помощью опции -0, (—null).

В следующем примере команда find выведет полные имена всех файлов в каталоге /var/www/.cache, а xargs передаст пути к файлам команде rm:

Использование xargs для обрезки пробелов

Xargs также можно использовать как инструмент для удаления пробелов с обеих сторон заданной строки. Просто передайте строку в команду xargs, и она выполнит обрезку:

Это может быть полезно при сравнении строк в скриптах оболочки.

Заключение

К настоящему времени вы должны хорошо понимать, как использовать команду Linux xargs. Для получения более подробной информации о каждой опции xargs прочитайте справочную страницу xargs.

Источник

Linux find and xargs

Ever done some work on a LINUX system and cannot remember where it was saved?

Enter the super-heros of LINUX — the ‘find’ and ‘xargs’ commands. Each is a powerful command in its own right, but when combined produce very useful output.

The Linux ‘find’ command will list files and directories that match the arguments to the command and pass specified tests. For example, to find all ‘txt’ files in the home directory, the following command can be used:

‘ means start at the user’s home directory and the -name is a test which means list only files with that particular name. Find has many tests but some of the most useful for finding files that have been updated recently are the -mtime and -mmin tests.

Читайте также:  Linux как скопировать файл по сети

mmin This test is used to find files modified within ‘n’ minutes mtime This test is used to find files modified within ‘n’ days

Some examples will make this clearer.

Find All Files Modified in the Last 90 Minutes

Note that the number of minutes (90) is prefixed with a ‘-‘. The reason for this will become apparent later. A sample output could be

It looks as if the ‘find’ command has listed files and directories. If we only want to see the files, add the -type test to the command to specify files only.

The sample output would then become

The information is now more concise, but which was the last file modified? You could issue a ‘ls’ command against each file in turn, but that could be very time consuming if there are more than a couple of files. What is needed is our other super-hero — xargs — with different powers.

Adding Xargs to Find

Xargs’ power lies in the fact that it can take the output of one command, in this case find, and use that output as arguments to another command. So, using the basic find command above, let us pass the output of find to xargs and get xargs to issue multiple ‘ls -l’ commands.

-type f -mmin -90 | xargs ls -l

The sample output would then become

Negative, Positive and Unsigned Times

In the above examples the number of minutes was specified as a negative number. This tell the find command that you wish to list files modified LESS THAN the specified number of minutes ago. If you had used a positive value, for example +300 , find would have returned a list of files modified MORE THAN 300 minutes ago. If you had used an unsigned value, for example 10 , find would have returned a list of files modified EXACTLY 10 minutes ago. This unsigned operand is not very useful for the mmins test.

Find All Files Modified More Than 5 Years Ago

In this example of the find and xargs command, we will use a positive time and the mtime test. The operand value to mtime is the number of 24 hour periods. It is not the number of days and the reason why will become apparent if you read ‘man find’. So, to see files over 5 years old will will use +1825 as the value for mtime. We have ignored leap years in calculating 5 years as 5*365 days. The command issued is

-type f -mtime +1825 |xargs ls -l

A sample output could be

Tell xargs when to Quit

One problem with the above approach is that a complete listing of the current directory will occur if the find command does not find any files! Xargs sees a list of zero files, but still issues the ‘ls -l’ command. To overcome this, simply use the xargs option ‘-r’ which means If the standard input does not contain any nonblanks, do not run the command. So, our command now becomes:

-type f -mtime +1825 |xargs -r ls -l

Note that the ‘-r’ is an xargs option and therefore comes after the xargs command name but before the command to be issued — in this case ‘ls -l’.

Summary

The find command is a very useful command for finding files in a LINUX system. Combining find with xargs makes it a very powerful command.

Источник

Команда xargs Linux

Возможность объединения нескольких команд Linux в терминале и использования их в качестве конвейера, когда каждая следующая команда получает вывод предыдущей — очень мощный и гибкий инструмент. Но команды можно объединять не только так. С помощью утилиты xargs вывод предыдущей команды можно передать в аргументы следующей.

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

Команда xargs в Linux

Синтаксис команды немного запутанный, но в нём можно разобраться:

$ первая_команда | xargs опции вторая_команда аргументы

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

Для настройки поведения утилиты xargs можно использовать опции. Давайте их рассмотрим:

  • -0, —null — использовать в качестве разделителя нулевой символ. Обычно он находится в конце строки. По умолчанию, в качестве разделителя используется пробел, перевод строки или табуляция;
  • -a, —arg-file — прочитать аргументы, которые надо передать команде из файла;
  • -d, —delimiter — использовать нестандартный разделитель строк;
  • -E, -e, —eof — индикатор конца файла, все символы после вхождения этой строки игнорируются;
  • -l, —max-lines — количество строк, передающихся в одну команду по умолчанию все;
  • -n, —max-args — количество параметров, которые передаются в одну команду, по умолчанию все;
  • -o, —open-tty — открывать новый терминал для дочерних процессов;
  • -p, —interactive — спрашивать пользователя о запуске каждой следующей команды;
  • -r, —no-run-if-empty — если входной поток данных пустой, команда не будет выполнена;
  • —show-limits — посмотреть ограничения на длину параметров в командной строке;
  • -t, —verbose — максимально подробный вывод утилиты.

Это далеко не все опции утилиты. Если вам нужны опции, которых нет в данной статье выполните команду:

А теперь давайте рассмотрим примеры использования xargs в Linux. Программа ожидает данные из входного потока. Поэтому если мы запустим её без параметров и наберем несколько слов, она просто их выведет. Например:

Чтобы подробнее понять что происходит можно использовать опцию -t:

Как видите, по умолчанию выполняется команда echo и ей передается всё, что было прочитано из стандартного ввода. Выше мы работали только с одной строкой. Давайте выведем все имена изображений из папки

/Изображения и отдадим их утилите xargs:

/Изображения | xargs -t echo

Читайте также:  Как узнать скачивается ли обновление windows 10

Как видите, одной команде echo были переданы все имена изображений. Если вам надо чтобы каждое изображение обрабатывала отдельно вызванная команда, надо использовать опцию -L или -n, Первая позволяет указать сколько строк надо передавать в одну команду. Вторая — сколько параметров. Различие существенное. В строке может быть несколько параметров разделённых пробелом. Сначала попробуем ограничиться одной строкой:

/Изображения | xargs -t -L1 echo

Но если попытаться ограничить количество параметров до одного, то возникнет проблема. Утилита будет думать, что имя файла это несколько параметров, поэтому будет дробить его. Зато теперь вы точно знаете как это работает:

/Изображения | xargs -t -n1 echo

По умолчанию строки разбиваются по символу перевода строки. С помощью опции -d можно указать свой разделитель. Разделитель должен быть совместим с функцией printf из Си. Это означает, что допускаются все символы, а также Escape последовательности вроде \n, \r, \t и других. Например, давайте сделаем разделителем дефис:

/Изображения | xargs -t -L1 -d — echo

Как и ожидалось, теперь команда будет дробить строки по дефису и выводить каждую полученную строку с помощью echo. В качестве разделителя строк можно использовать нулевой символ. Это символ, который обозначается последовательностью \0. Он используется в программах на Си для обозначения завершения строки, и необходим практически для всех встроенных функций работающих со строками.

Для того чтобы разбивать строки по этому символу используется опция -0 или —null. Но для того чтобы всё сработало надо чтобы и поставляющая данные команда тоже выводила этот символ. Такая функция есть у команды find, она имеет опцию -print0. Например, выведем снова все имена изображений из папки

/Изображения с названием Рабочее место:

/Изображения -name «Рабочее место*» -type f -print0 | xargs -t -0 -L1 echo

А если такой параметр не передать, то вы получите ошибку:

/Изображения -name «Рабочее место*» -type f -print0 | xargs -t -L1 echo

Если команда выполняет какие-нибудь опасные действия, вы можете попросить утилиту спрашивать разрешения перед выполнением следующей команды:

/Изображения -name «Рабочее место*» -type f | xargs -p -t -L1 echo

Выводы

В этой статье мы рассмотрели что из себя представляет команда xargs Linux. Как видите это довольно простая утилита, которая перенаправляет вывод одной программы в аргументы другой.

Источник

Everything CLI

If you want to search files by a pattern and then apply something to the results you have at least two choices. You can use find. -exec or you can pipe the results to xargs. There are also two different choices for find -exec and find | xargs that will have a dramatic impact on performance. So what is the difference and which one should you choose?

We start with a very basic example

1. Search within files

Search for files only that end with .php and look for the string $test inside those files:

They all seem to do the same. Let’s see if they all find the same amount of results:

No difference either, let’s look at the commands in detail.

1.1 What is equal in find -exec

The above is all the same for all three queries. Let’s have a look at the grep command:

1.2 What is different in find -exec

1.2.1 find \;

<> Is a placeholder for the result found by find
\; Says that for each found result, the command (in this case ‘grep’) is executed once with the found result

So in the above example ‘grep’ is executed as many times as a file with the specified pattern has been found:

1.2.2 find +

<> Is a placeholder for the result found by find
\+ All result lines are concatenated and the command (in this case ‘grep’) is executed only a single time with all found results as a parameter

So in the above example ‘grep’ is executed only once and its parameter are all files found with the specified pattern.

1.3 What is equal in find | xargs

-print0 Tells find to print all results to std, each separated with the ASCII NUL character ‘\000’
-0 Tells xargs that the input will be separated with the ASCII NUL character ‘\000’

You have to use both or neither of them. The advantage is that all results will be handed over to xargs as a single string without newline separation. NUL charater separation is a way to escape files which also contain spaces in their filenames.

All reults by find are piped to xargs and you can now execute commands on them.

1.4 What is different in find | xargs

1.4.1 xargs with -n1

-n1 Tells xarg to execute the command [cmd] with only one argument (In this case only one file found by find). This is equal to:

So in the above example ‘grep’ is executed as many times as a file with the specified pattern has been found:

1.4.2 xargs without -n

If no -n[int] is specified, xargs uses the default of -n5000 (see man xargs ).
This means that xargs uses up to 5000 parameters for the command and executes it once, instead of 5000 times.
This is equal to:

So in the above example ‘grep’ is executed only once and its parameter are all files found with the specified pattern.

1.5 Performance

Let’s see how those commands scale on a large folder with 37 GB of files.

So obviously find + and xargs (without -n1) are much faster because there is no overhead in fork and exec. It decreases I/O dramatically and seen from the times commands they are up to 6x faster.

1.6 Difference between find -exec and find | xargs

Now that each find command and each xargs command has been discussed, there is still a difference between the actual find -exec and find | xargs.

1.6.1 Exit code

find -exec returns the exit code of find itself instead of the subcommand.
find | xargs returns the exit code of the subcommand.

Читайте также:  Драйвер для принтера hp deskjet f300 для windows 10

1.6.2 Parallelism

If you use find | xargs to execute each command separately (-n1) you can also do that in parallel mode in order to boost performance.
Let’s check out the performance again on an 8-core processor with 8 simultaneous xargs processes (-P8)

This seems to be much faster than in normal mode.

Finally let’s have a look at another example to evaluate the exit code.

2. Check PHP files for syntax errors

In this example I want to find PHP syntax errors in all php files in the current directory recursively

2.1 Note

In this example we cannot use \+ for find and must use -n1 for xargs, because the subcommand php -l only accepts one file at a time.

2.2 find -exec

Even though php -l fails and exits with 1 somewhere at the beginning, find -exec continues and finally exits with zero.

2.3 find | xargs

The command immediately stops executing. Why? Because the subcommand failed and this is the nature of piping commands. We can now see the main difference between find -exec and find | xargs:

find -exec will continue on every file, even if -exec fails, but find | xargs will immediately stop once there is an error in the piped command.

3. Conclusion

3.1 Parameter Method

It depends on the subcommand whether you have to use \; for find and -n1 for xargs. If the subcommand is able to use multiple inputs, then use + and no -n1. If the subcommand can only take one argument, you have to use \; and -n1.

3.2 find -exec vs find | xargs

If you need to stop the execution on failed subcommands, you need to use xargs. If you want or need to continue the on failed subcommands you have to use find -exec.

3.3 More on xargs

xargs has some additional useful parameter you should be aware of:

For all others I suggest reading the manpage.

36 comments on “find -exec vs. find | xargs”

Very nice article. Thank you.

Excellent article, very well written and informative!

Why did you escape the asterisk wildcard. The command seems to function the same without escaping

If you refer to find . -name \*.php this is answered by the man page

I enjoyed reading your article. Very informative. Keep up good work.

Very nice text , nice you did a performance test. Good work.

Very useful article indeed! Thank you so much!

In section 1.4.2 you wrote that xargs without -n[int] is equal to:

I’m confused by the +; at the end. Everywhere else in the article + and ; are not used together; rather they are contrasted as different options. Can you explain that in more detail?

That’s a typo. He meant find . -exec [cmd] <> \+»

With xargs -n you can reduce the time wasted on forking, without exceeding the argument limit of whatever command you’re executing.. e.g.

I needed to remove 1.2 million files in a directory older than 30 days, and of course rm won’t take the full argument list, but calling rm separately on every single file is not optimal either. So.

find . -name \*.log -mtime +30 | xargs -n 500 rm

Feeds 500 files to rm at a time.

On the other hand, I found if the filenames had special characters in them, such as single quotes, then find …. -exec rm <> \; handled them without complaint, while piping them to xargs -n 1 or -n 500 rm would blow up on those quotes. It appears that -exec <> is smarter about quoting the filenames.

Does this works on an AIX system with same parameters?

Thank you for this great article, I have shared itt on Facebook.

Well written and very interesting.

Explanation of timing differences of using find and find with xargs, and especially with the -P8 or however many cores has opened up possibility for making things way more efficient. Thanks.

Are you aware that if find returns nothing, and xargs is used, xargs will run the command on all files in the current directory? I suspect find is echoing a null to xargs and that causes xargs to process the required command for all files in the current directory.

For example, find all the files named *.txt exactly 1205 bytes in size and list them:

find . -maxdepth 1 -type f -name «*.txt» -size 1205c -print0 | xargs -0 ls -l

On my test system, that lists 6 files and is correct. However, change it to something ridiculous so that find finds nothing, change the ‘c’ to a ‘G’ (Gigabytes) and we have the following

find . -maxdepth 1 -type f -name «*.txt» -size 1205G -print0 | xargs -0 ls -l

And now the result is a listing of every file and directory, in the current directory – 91 in total.

This could be a problem in situations where you are deleting some files ….. ask me how I found out?

In (potentially) “dangerous” situations like that, you probably want to pass the “-r” parameter to “xargs”.

Or just use “find”‘s “-delete” action instead of piping it to “xargs”.

the solution is:

find … -print0|xargs -0 rm —

the solution is:

find … -print0|xargs -0 rm —

thanks, a very good article !

Well organized information, thanks a lot!

Very informative and helpful. Thanks.

Comparison and examples always make things much clear. Great article.

A truly valuable article. Many thanks.

So useful, thank you!

Cool!Thanks for your sharing!

Can multiple executions, whether via | xarg or -exec, be run on find results? What about piping within | xarg or -exec?

Thank you for this article, good learning for me!

This is wonderfully concise and insightful! Thank you so much for helping us all.

Источник

Оцените статью