2013-07-01 26 views
12

Kod mojej witryny używa tego fragmentu kodu do automatycznego wdrożenia na serwerze (Ubuntu).Zignoruj ​​puste wyniki dla xargs w systemie 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

Co to polecenie robi to cd do katalogu kasie, biegnie svn status, a następnie pobiera nazwę pliku ($2), usuwa katalog deploy i wszystkie jego pliki z listy (I don nie chcesz tego odwrócić). Jeśli nie ma argumentów, to nie uruchamia polecenia svn revert, inaczej robi.

Niestety, xargs -r nie działa na moim komputerze (Mac OS X 10.8). Więc utknąłem tutaj, czy ktoś może pomóc?

+1

Czy to jest kod Pythona? – tripleee

Odpowiedz

4

Rzeczywiście, implementacja BSD xargs nie ma flagi -r (--no-run-if-empty). Wersja GNU w Linuksie to ma.

Oto jeden sposób, aby obejść ten problem w sposób, który działa zarówno w systemie Linux i BSD:

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

grep ... || echo : w środku wygeneruje linię z : w nim w przypadku wyjścia grep jest pusty. To jest nieco brudny, ponieważ xargs nadal będzie uruchamiał polecenie svn revert :. Jeśli twoje repozytorium nie zawiera pliku :, nie powinno to mieć żadnego efektu, więc może być akceptowalne. : może być czymkolwiek innym, o ile w twoim repozytorium nie ma takiego pliku.

Wreszcie, jak @tripleee zauważono, grep ... || echo : muszą być zawarte w (...), ponieważ:

|| ma wyższy priorytet niż |, a więc kończy się (pierwszego) rurociągu.

Twój kod wygląda jak ciąg znaków w języku Python. To będzie bardziej czytelny w ten sposób:

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) 

Zrobiłem kilka zmian do pierwotnego:

  • Przeniesiony logikę grep wewnątrz awk, jak @tripleee sugerowane. Zauważ, że skoro grep Hack nie jest już potrzebny, nie ma też więcej trzeba zawinąć w ciągu (...)
  • upuścił tac, ponieważ nie widzę sensu w to
  • upuścił -R z svn revert, bo don Myślę, że go potrzebujesz
+0

Jak to w ogóle pomaga? Problem nie jest pustymi liniami, to jest * nie * liniami. – tripleee

+0

@tripleee Chce użyć flagi '-r' z' xargs', ale nie może, ponieważ nie istnieje w BSD. Chce użyć flagi, ponieważ nie chce uruchomić 'svn revert -R' bez argumentów. 'svn revert -R something' odwróci zmiany tylko w" coś ", a' svn revert -R' bez argumentów przywróci wszystko. On nie chce przywrócić wszystkiego. – janos

+0

Rozumiem pytanie. 'xargs -r' jest użyteczne, aby ukryć akcję, gdy nie ma danych wejściowych; "grep." nie robi nic, aby wygenerować dane wejściowe, gdy ich nie ma (i jak to możliwe?), więc sugerowane obejście tej odpowiedzi w ogóle nie pomaga. – tripleee

3

Nie jest ładna, ale miejmy nadzieję obejść.

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 

nie jestem przekonany, że tac jest konieczne lub pożyteczne.Przepisałem pierwszy kod grep do skryptu Awk ze względów wydajnościowych i estetycznych.

Aby rozwiązać ogólny "my xargs brakuje -r" problem, istota rozwiązania jest konwersja

stuff | xargs -r cmd 

do

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

nienotowanych $var będzie działać tylko wtedy, gdy nie ma zawierać nazwy plików ze spacjami lub innymi niespodziankami; ale wtedy bare-bones xargs bez rozszerzeń GNU cierpi na ten sam problem.

1

Urządzenie -r dla xargs nie działa w systemie OS X, ponieważ jest to rozszerzenie GNU. Jeśli chodzi o obejście problemu, powinieneś podać jakiś fałszywy plik, który może być parsowany przez xargs lub nie wywoływać komendy, gdy nie ma żadnych argumentów (które można sprawdzić wcześniej).

Metoda z zastosowaniem tymczasowego pliku (lub jakikolwiek inny zastępczy):

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

Korzystanie stan w skorupkach:

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

Patrz także: Ignore empty result for xargs

0

Bash reimplementacja xargs czynienia z -r argument:

#!/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]