Рассмотрим эту команду:
ls /mydir/*.txt | xargs chown root
Намерение состоит в том, чтобы изменить владельцев всех текстовых файлов в mydir
root
Проблема в том, что если нет .txt
файлов, mydir
то xargs выдает ошибку, сообщающую, что путь не указан. Это безвредный пример, потому что выдается ошибка, но в некоторых случаях, например, в сценарии, который мне нужно здесь использовать, предполагается, что в качестве текущего каталога используется пустой путь. Таким образом, если я запускаю эту команду с /home/tom/
тех пор, если нет результатов для ls /mydir/*.txt
всех файлов /home/tom/
, их владельцы меняются на root.
Так как же я могу заставить xargs игнорировать пустой результат?
ls
для программного использования; см. mywiki.wooledge.org/ParsingLsgit branch --merged | grep -v '^* ' | xargs git branch -d
, который также не срабатывает при пустом вводеОтветы:
Для GNU
xargs
вы можете использовать опцию-r
или--no-run-if-empty
:источник
brew install findutils
.findutils
Неfileutils
.Пользователи не-GNU xargs может воспользоваться
-L <#lines>
,-n <#args>
,-i
и-I <string>
:Имейте в виду, что xargs разбивает строку в пробелах, но доступны цитирование и экранирование; RTFM для деталей.
Кроме того, как упоминает Дорон Бехар, этот обходной путь не переносим, поэтому могут потребоваться проверки:
источник
xargs
не поддерживает--no-run-if-empty
коммутатор и пытается запустить аргумент команды без ввода STDIN (это имеет место в Solaris 10). Версии в других unixes могут просто игнорировать пустой список (например, AIX).echo '' | xargs -n1 echo blah
ничего не делает; тогда какecho 'x' | xargs -n1 echo blah
печатает "бла".ls /mydir/*.txt | xargs -n 1 -I {} chown root {}
как предполагает этот ответ.echo '' | xargs -n1 echo blah
печатаетblah
с GNUxargs
.man xargs
говорит--no-run-if-empty
.источник
С точки зрения
xargs
, вы можете использовать-r
как предложено, однако это не поддерживается BSDxargs
.В качестве обходного пути вы можете передать какой-то дополнительный временный файл, например:
или перенаправить его stderr в null (
2> /dev/null
), напримерДругой лучший подход - перебрать найденные файлы с помощью
while
цикла:Смотрите также: Игнорировать пустые результаты для xargs в Mac OS X
Также обратите внимание, что ваш метод смены разрешений не очень хорош и не рекомендуется. Определенно, вы не должны анализировать выходные данные
ls
команды (см .: Почему вы не должны анализировать выходные данные команды ls ). Особенно, когда вы запускаете команду от имени пользователя root, поскольку ваши файлы могут состоять из специальных символов, которые могут интерпретироваться оболочкой или представлять файл с пробелом вокруг/
, тогда результаты могут быть ужасными.Поэтому вы должны изменить свой подход и использовать
find
вместо него команду, напримеристочник
while IFS= read -r -d '' file
это действительно. Вы можете объяснить?В OSX: переопределение Bash для
xargs
работы с-r
аргументом, вставьте это, например, в$HOME/bin
и добавьте его вPATH
:источник
Это поведение GNU xargs, которое может быть подавлено с помощью -r, --no-run-if-empty.
Вариант xargs * BSD имеет такое поведение по умолчанию, поэтому -r не требуется. Начиная с FreeBSD 7.1 (выпущенной в январе 2009 г.), аргумент -r принимается (ведьма ничего не делает) по соображениям совместимости.
Лично я предпочитаю использовать longopts в скриптах, но поскольку * BSD xargs не использует longopts, просто используйте «-r», и xargs будет действовать так же на * BSD и на системах Linux
К сожалению, xargs в MacOS (в настоящее время MacOS Mojave) не поддерживает аргумент "-r".
источник