2013-07-01 1 views
12

Код для моего сайта использует этот фрагмент кода для автоматического развертывания на сервере (Ubuntu).Игнорировать пустые результаты для xargs в Mac OS X

cmd = 'cd ' + checkout_dir + ' && ' + svn_command + " st | awk '{print $2}' | grep -v ^deploy | tac | xargs -r" + svn_command + " revert -R && " + svn_command + ' up -r ' + options.revision

Что эта команда делает это cd в каталог кассы, работает svn status, а затем извлекает имя файла ($2), удаляет каталог deploy и все его файлы из списка (я не 't хочу вернуть его). Если аргументов нет, он не запускает команду svn revert, иначе это произойдет.

К сожалению, xargs -r не работает на моей машине (Mac OS X 10.8). Так что я застрял здесь, может ли кто-нибудь помочь?

+1

Это код Python или что? – tripleee

ответ

4

Действительно, в реализации BSD xargs нет флага -r (--no-run-if-empty). В версии GNU в Linux есть.

Вот один из способов обойти эту проблему таким образом, который работает как в Linux и BSD:

... | (grep -v ^deploy || echo :) | xargs svn revert 

grep ... || echo : в середине будет генерировать строку с : в нем в случае выхода grep пусто. Немного грязный, потому что xargs по-прежнему будет выполнять команду svn revert :. Если ваш репозиторий не содержит файл :, тогда это не должно иметь никакого эффекта, поэтому оно может быть приемлемым. : может быть чем угодно, если в вашем репозитории нет такого файла.

Наконец, как @tripleee указывалось, grep ... || echo : должен быть заключен в пределах (...), потому что:

|| имеет более высокий приоритет, чем |, и таким образом завершает (первый) трубопровод.

Ваш код выглядит как строка Python. Это будет более удобным для чтения таким образом:

kwargs = { 
    'svn': svn_command, 
    'dir': checkout_dir, 
    'revno': options.revision, 
} 
cmd = "cd {dir} && {svn} st | awk -v r=1 '$2 ! ~ /deploy/ {{ print $2; r=0 }} END {{ r || print \":\" }}' | xargs {svn} revert && {svn} up -r {revno}".format(**kwargs) 

Я сделал некоторые изменения в оригинал:

  • Переехал логику grep внутри awk как @tripleee предложил. Обратите внимание на то, что, поскольку grep хак больше не нужен, там также нет больше необходимости завернуть в (...)
  • уронил tac, так как я не вижу смысла в его
  • уронил -R из svn revert, потому что я не Думаю, что это необходимо
+0

Как это вообще помогает? Проблема заключается не в пустых строках, а в линиях * no *. – tripleee

+0

@tripleee Он хочет использовать флаг '-r'' xargs', но не может, поскольку он не существует в BSD. Он хочет использовать флаг, потому что он не хочет запускать 'svn revert -R' без аргументов. 'svn revert -R something' вернет изменения только в« что-то », а' svn revert -R' без аргументов вернет все. Он не хочет возвращать все. – janos

+0

Я понимаю вопрос. 'xargs -r' полезен для подавления действия, когда нет ввода; 'grep .' ничего не делает для генерации ввода, когда его нет (и как это может быть?), поэтому предлагаемый обходной путь в этом ответе не помогает вообще. – tripleee

3

Не очень, но, надеюсь, обходной путь.

cmd = 'cd ' + checkout_dir + ' && ' + 
    'r=$(' svn_command + ' st | ' + 
     "awk '$2 !~ /^deploy/{print $2}' | tac) && " + 
    'test "$r" && ' + 
    svn_command + ' revert -R $r && ' + 
    svn_command + ' up -r ' + options.revision 

Я не уверен, что tac является необходимым или полезным.Я реорганизовал первый grep в сценарий Awk по эффективности и эстетическим соображениям.

Для решения общего «мой xargs не хватает -r» проблемы, суть решения заключается в преобразовании

stuff | xargs -r cmd 

в

var=$(stuff) 
test "$var" && cmd $var 

котировочный $var будет работать, только если он не содержать имена файлов с пробелами или другими сюрпризами; но тогда голые кости xargs без расширений GNU страдают от одной и той же проблемы.

1

-r для xargs не работает над OS X, так как это расширение GNU. Что касается обходного пути, вы должны указать некоторый фиктивный файл, который может быть проанализирован xargs или не вызывать команду, если нет аргументов (которые можно проверить ранее).

Метод с использованием временного файла (или любой другой заполнитель):

some_cmd ... | xargs svn revert $(mktemp) 

Использование условия в оболочке:

files=$(cd checkout_dir && ... | tac) 
if [ -n "$files" ]; then 
    echo $files | xargs && ... 
fi 

Смотрите также: Ignore empty result for xargs

0

Bash перевыполнение xargs дело с -r аргумент:

#!/bin/bash 
stdin=$(cat <&0) 
if [[ $1 == "-r" ]] || [[ $1 == "--no-run-if-empty" ]] 
then 
    # shift the arguments to get rid of the "-r" that is not valid on OSX 
    shift 
    # wc -l return some whitespaces, let's get rid of them with tr 
    linecount=$(echo $stdin | grep -v "^$" | wc -l | tr -d '[:space:]') 
    if [ "x$linecount" = "x0" ] 
    then 
     exit 0 
    fi 
fi 

# grep returns an error code for no matching lines, so only activate error checks from here 
set -e 
set -o pipefail 
echo $stdin | /usr/bin/xargs [email protected]