Когда xargs необходим?

Кажется, что причина для моей проблемы была nfs-kernel-server экспортировал каталог. nfs-kernel-server вероятно, идет позади нормальных открытых файлов и таким образом не перечислен lsof и fuser.

Когда я остановился nfs-kernel-server Я мог umount каталог.

Я сделал страницу с примерами всех решений до сих пор здесь: http://oletange.blogspot.com/2012/04/umount-device-is-busy-why.html

136
21.11.2018, 08:46
6 ответов

Различие находится, в каких данных целевая программа принимает.

Если Вы просто используете канал, он получает данные по STDIN (стандартный входной поток) как необработанная груда данных, что он может отсортировать одну строку за один раз. Однако некоторые программы не принимают свои команды по стандарту в, они ожидают, что это будет разъяснено в аргументах команде. Например, touch берет имя файла в качестве параметра на командной строке как так: touch file1.txt.

Если у Вас есть программа, которой выходные имена файлов по стандарту и хотят использовать их в качестве аргументов touch, необходимо использовать xargs который считывает потоковые данные STDIN и преобразовывает каждую строку, в космос разделил аргументы команде.

Эти две вещи эквивалентны:

# touch file1.txt
# echo file1.txt | xargs touch

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

144
27.01.2020, 19:29
  • 1
    Предупреждение чувствует немного строки мне. Из двух общих опций получить поток на командную строку (xargs и $(...)), xargs намного более безопасен, чем замена команды. И я не могу вспомнить никогда случайную встречу с законным именем файла с новой строкой в нем. Разве выход и проблемы ловушек расширения слова с заменой команды не, не xargs? –  camh 20.11.2011, 00:31
  • 2
    @camh: они - потенциальные ловушки с обоими. В оболочке необходимо волноваться об именах файлов, разделяемых на пробелах, вкладках и новых строках. В xargs только необходимо волноваться о новых строках. В xargs, если Вы производитесь, отформатирован правильно, можно разделить слова/имена файлов на символе NUL вместо этого (xargs -0), который полезен в сочетании с find -print0. интересный –  Ken Bloom 20.11.2011, 03:22
  • 3
    Делает xargs назовите программу через оболочку с пространством разделенным args, или делает это, на самом деле создают список аргументов внутренне (например, для использования с execv/execp)? –  detly 20.11.2011, 11:55
  • 4
    , Он создает его внутренне и использует execvp, таким образом, это безопасно. Кроме того, GNU xargs (как используется на Linux и немногих других) позволяет Вам указать новую строку как свой разделитель с -d \n, хотя BSD xargs (OSX и др.), кажется, не поддерживает эту опцию. –  fluffy 21.11.2011, 02:20

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

Например:

$ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8

закодирует *.wav => *.flac, с помощью трех процессов сразу (-P 3).

73
27.01.2020, 19:29
  • 1
    Ничего себе. Я должен был знать это неделю назад, когда я делал точно то же самое (кроме использования OGG) с 50 ГиБ WAVs. вид :) –  Alois Mahdal 14.05.2012, 00:38
  • 2
    , почему бы не использовать - исполнительный параметр, которые находят, имеет? –  Evgeny 11.09.2012, 12:46
  • 3
    @Evgeny -exec параметр не будет задания параллельного процесса. –  amphetamachine 18.09.2012, 15:56

xargs особенно полезен, когда Вы имеете список filepaths на stdin и хотите сделать что-то с ними. Например:

$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

Давайте исследуем это шаг за шагом:

$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....

Другими словами, наш вход является списком путей, к которым мы хотим сделать что-то.

Для обнаружения, что xargs делает с этими путями должен добавить хороший прием echo перед Вашей командой, как так:

$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....

-n 1 аргумент заставит xargs превратить каждую строку в собственную команду. sed -i "s/color/colour/g" команда заменит все случаи color с colour для указанного файла.

Обратите внимание, что это только работает, если у Вас нет пробелов в Ваших путях. Если Вы делаете, необходимо использовать завершенные пути пустого указателя, как введено для xargs путем передачи -0 флаг. Использование в качестве примера было бы:

$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"

Который делает то же как, что мы описали выше, но также и работы, если один из путей имеет пространство в нем.

Это работает с любой командой, которая производит имена файлов, как произведено такой как find или locate. Если Вы, действительно оказывается, используете его в репозитории мерзавца с большим количеством файлов, хотя, могло бы быть более эффективно использовать его с git grep -l вместо git ls-files, как так:

$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

git grep -l "color" "*.tex" команда даст список "*.tex" файлов, содержащих фразу "цвет".

24
27.01.2020, 19:29

Ваш первый аргумент иллюстрирует различие вполне хорошо.

\ls | grep Cases | less позволяет Вам просмотреть список имен файлов, произведенных ls и grep. Не имеет значения, что они, оказывается, имена файлов, они - просто некоторый текст.

\ls | grep Cases | xargs less позволяет Вам просмотреть файлы, имена которых производятся первой частью команды. xargs берет список имен файлов, как введено и команды на ее командной строке, и выполняет команду с именами файлов на ее командной строке.

При рассматривании использование xargs, имейте в виду, что это ожидает вход, отформатированный странным способом: разграниченный пробелом, с \, ' и " используемый для заключения в кавычки (необычным способом, потому что \ не специальные внутренние кавычки). Только используйте xargs если Вы Ваши имена файлов не содержите пробел или \'".

7
27.01.2020, 19:29
  • 1
    @Gilles: xargs имеет -0, --null опция обойти проблему пробелов (очень вероятно, что я узнал, что от Вас :), таким образом, я предполагаю, что Вы обращаетесь к без опций xarg звоните, но я озадачен Вашей ссылкой на кавычки. У Вас есть ссылка или пример относительно этого?.. (PS. | xargs less удобный "прием" +1..спасибо.. –  Peter.O 01.12.2011, 22:59

В Вашем примере Вы не должны использовать xargs вообще с тех пор find сделает точно и безопасно что Вы хотите сделать.

Точно, что Вы хотите использовать find :

find -maxdepth 1 -name '*Cases*' -exec touch {} +

В этом примере -maxdepth 1 средства только ищут в текущем каталоге, не убывайте ни в какие подкаталоги; по умолчанию находка посмотрит во всех подкаталогах (который часто является, что Вы хотите), если Вы ограничение это с maxdepth. {} название файла, которым заменят в его месте и + один из двух маркеров конца команды, другого существа ;. Различие между ними - это ; должностное лицо средств команда на каждом файле по одному, тогда как + должностное лицо средств команда на всех файлах сразу. Обратите внимание, однако, что Ваша оболочка, вероятно, попытается интерпретировать ; с самостоятельно, таким образом, необходимо будет выйти из него также \; или ';'. Да, find имеет много небольших раздражений как это, но его питание больше, чем восполняет его.

Оба find и xargs хитры для изучения сначала. Помочь Вам учиться xargs попытайтесь использовать -p или --interactive опция, которая покажет Вам команду, она собирается выполнить и предложить Вам, действительно ли Вы хотите выполнить ее.

Так же с find можно использовать -ok вместо -exec предлагать Вам, хотите ли Вы выполнить команду.

Существуют времена, тем не менее, когда find не сможет сделать все, что Вы хотите, и это то, где xargs входит. -exec команда только примет один экземпляр {} появление, поэтому если Вы получили бы ошибку с find -type f -exec cp {} {}.bak \; таким образом, Вы могли вместо этого сделать это как так: find -type f -print0 | xargs -0 -l1 -IX cp X X.bak

Можно узнать больше о Командах выполнения в руководстве Findutils GNU.

Кроме того, я упомянул это find безопасно делает то, что Вы хотите, потому что, когда Вы имеете дело с файлами, Вы собираетесь встретиться с пробелами и другими символами, которые вызовут проблемы с xargs если Вы не используете -0 или --null опция наряду с чем-то, что генерирует входные параметры, завершенные нулевым символом вместо пробела.

4
27.01.2020, 19:29

xargs (наряду с find, sort, du, uniq, perl и немногие другие), принимает, что переключатель командной строки говорит, что "STDIN имеет список файлов, разделенных NUL (0x00) байт". Это помогает обработать имена файлов с пробелами и другими забавными символами в них. Имена файлов не содержат NULs.

1
27.01.2020, 19:29
  • 1
    я думаю, что Вы имеете в виду "имена файлов, не может содержать, аннулирует". –  amphetamachine 23.11.2011, 07:50

Теги

Похожие вопросы