Rozważ to polecenie:
ls /mydir/*.txt | xargs chown root
Intencją jest zmiana właścicieli wszystkich plików tekstowych mydir
na root
Problem polega na tym, że jeśli nie ma żadnych .txt
plików, mydir
xargs wyświetla błąd informujący, że nie określono ścieżki. Jest to nieszkodliwy przykład, ponieważ generowany jest błąd, ale w niektórych przypadkach, na przykład w skrypcie, którego muszę tutaj użyć, przyjmuje się, że bieżącym katalogiem jest pusta ścieżka. Więc jeśli uruchomię to polecenie /home/tom/
odtąd, jeśli nie będzie wyników dla, ls /mydir/*.txt
a wszystkie pliki w katalogu /home/tom/
mają swoich właścicieli zmienionych na root.
Więc jak mogę xargs zignorować pusty wynik?
ls
do celów programowych; patrz mywiki.wooledge.org/ParsingLsgit branch --merged | grep -v '^* ' | xargs git branch -d
, który również nie działa przy pustych danych wejściowychOdpowiedzi:
W przypadku GNU
xargs
możesz użyć opcji-r
lub--no-run-if-empty
:źródło
brew install findutils
.findutils
Niefileutils
.Użytkownicy xargs non-gnu mogą skorzystać z
-L <#lines>
,-n <#args>
,-i
i-I <string>
:Należy pamiętać, że xargs dzieli linię w spacji, ale dostępne są cytowania i zmiany znaczenia; RTFM po szczegóły.
Ponadto, jak wspomina Doron Behar, to obejście nie jest przenośne, więc mogą być potrzebne kontrole:
źródło
xargs
nie obsługuje--no-run-if-empty
przełącznika i próbuje uruchomić argument polecenia bez danych wejściowych STDIN (tak jest w Solarisie 10). Wersje innych unixów mogą po prostu zignorować pustą listę (np. AIX).echo '' | xargs -n1 echo blah
nic nie robi; podczas gdyecho 'x' | xargs -n1 echo blah
drukuje „bla”.ls /mydir/*.txt | xargs -n 1 -I {} chown root {}
jak sugeruje ta odpowiedź.echo '' | xargs -n1 echo blah
drukujeblah
z GNUxargs
.man xargs
mówi--no-run-if-empty
.źródło
Jeśli chodzi o
xargs
, możesz używać-r
zgodnie z sugestią, jednak nie jest to obsługiwane przez BSDxargs
.Aby obejść ten problem, możesz przekazać dodatkowy plik tymczasowy, na przykład:
lub przekieruj jego stderr na null (
2> /dev/null
), npInnym lepszym podejściem jest iteracja znalezionych plików za pomocą
while
pętli:Zobacz także: Zignoruj puste wyniki dla xargs w Mac OS X.
Pamiętaj również, że twoja metoda zmiany uprawnień nie jest świetna i jest odradzana. Zdecydowanie nie powinieneś analizować danych wyjściowych
ls
polecenia (zobacz: Dlaczego nie powinieneś analizować danych wyjściowych polecenia ls ). Zwłaszcza gdy uruchamiasz polecenie przez root, ponieważ twoje pliki mogą składać się ze znaków specjalnych, które mogą być interpretowane przez powłokę lub wyobrażać sobie plik zawierający znak spacji/
, wtedy wyniki mogą być straszne.Dlatego powinieneś zmienić swoje podejście i
find
zamiast tego użyć polecenia, npźródło
while IFS= read -r -d '' file
ważne jest. Możesz wytłumaczyć?W OSX: Bash reimplementation
xargs
radzenia sobie z-r
argumentem, wstaw to np. Do$HOME/bin
i dodaj go doPATH
:źródło
Jest to zachowanie GNU xargs, które można stłumić za pomocą opcji -r, --no-run-if-empty.
Wariant * BSD xargs ma takie zachowanie domyślnie, więc -r nie jest potrzebne. Od wersji FreeBSD 7.1 (wydanej w styczniu 2009) argument -r jest akceptowany (czarownica nic nie robi) z powodów kompatybilności.
Osobiście wolę używać skryptów longopts, ale ponieważ xargs * BSD nie używa longopsów, użyj po prostu „-r”, a xargs będzie działał tak samo na * BSD i systemach Linux.
xargs na MacOS (obecnie MacOS Mojave) niestety nie obsługuje argumentu „-r”.
źródło