$ ls *mp3 | xargs mplayer
Playing Lemon.
File not found: 'Lemon'
Playing Tree.mp3.
File not found: 'Tree.mp3'
Exiting... (End of file)
Moje polecenie kończy się niepowodzeniem, ponieważ plik „Lemon Tree.mp3” zawiera spacje, więc xargs myśli, że to dwa pliki. Czy mogę sprawić, by find + xargs działał z takimi nazwami plików?
ls |grep mp3 |sed -n "7p"
ciebie możesz po prostu użyćecho "Lemon Tree.mp3"
.Odpowiedzi:
xargs
Komenda bierze białe znaki (spacje, tabulatory, nowych linii) jako ograniczniki. Możesz zawęzić listę tylko do nowych znaków wiersza („\ n”) za pomocą-d
opcji takiej jak ta:Działa tylko z GNU xargs. W przypadku systemów BSD użyj takiej
-0
opcji:Ta metoda jest prostsza i działa również z GNU xargs.
źródło
-E
, np .:xargs -E '\n'
Narzędzie xargs odczytuje ze standardowego wejścia łańcuchy rozdzielone spacją, tabulatorem, znakiem nowej linii i końca pliku i wykonuje narzędzie z łańcuchami jako argumentami.
Chcesz uniknąć używania spacji jako separatora. Można to zrobić, zmieniając ogranicznik dla xargs. Zgodnie z instrukcją:
Jak na przykład:
Aby odpowiedzieć na pytanie dotyczące odtwarzania siódmego mp3; łatwiej jest uruchomić
źródło
find
i GNUxargs
; nie wszystkie wersje tych programów obsługują te opcje (choć należy uzasadnić, że powinny).find
z-print0
ixargs
z-0
. Jednak AFAIK, HP-UX, AIX i Solaris nie (ale mam nadzieję, że będę poprawiony: HP-UX 11i nie; Solaris 10 nie; AIX 5.x nie; ale to nie są bieżące wersje ). Na przykład nie byłoby trudno zmienićsed
„linie” kończące się'\0'
na'\n'
, a POSIX 2008 ułatwiłbygetdelim()
zarządzanie.Próbować
zamiast
źródło
xargs w systemie MacOS nie ma opcji -d, dlatego w tym rozwiązaniu zastosowano opcję -0.
Poproś ls, aby wyprowadzał jeden plik w wierszu, a następnie przetłumacz znaki nowej linii na wartości null i powiedz xargs, aby używał wartości null jako separatora:
ls -1 *mp3 | tr "\n" "\0" | xargs -0 mplayer
źródło
Pomogło to w moim przypadku usunąć różne pliki ze spacjami. Powinno też działać z mplayerem. Niezbędną sztuczką są cytaty. (Testowany na Linux Xubuntu 14.04.)
źródło
Odpowiedź Dick.Guertina [1] sugeruje, że można uciec ze spacji w nazwie pliku, jest cenną alternatywą dla innych sugerowanych tu rozwiązań (takich jak użycie znaku pustego zamiast separatora zamiast białych znaków). Ale może być prostsze - tak naprawdę nie potrzebujesz wyjątkowej postaci. Możesz po prostu dodać dodane spacje bezpośrednio:
Ponadto grep jest konieczny tylko wtedy, gdy chcesz tylko pliki ze spacjami w nazwach. Bardziej ogólnie (np. Podczas przetwarzania partii plików, z których niektóre mają spacje, niektóre nie), po prostu pomiń grep:
Wtedy oczywiście nazwa pliku może zawierać inne białe znaki niż puste (np. Tabulator):
Zakłada się, że masz sed, który obsługuje -r (rozszerzone wyrażenia regularne), takie jak GNU sed lub najnowsze wersje bsd sed (np. FreeBSD, który oryginalnie przeliterował opcję „-E” przed FreeBSD 8 i obsługuje zarówno -r & -E dla kompatybilności przynajmniej przez FreeBSD 11). W przeciwnym razie możesz użyć podstawowego wyrażenia wyrażenia regularnego w klasie wyrażeń regularnych i ręcznie wprowadzić znaki spacji i tabulatorów w
[]
ogranicznikach.[1] Być może jest to bardziej odpowiednie jako komentarz lub edycja tej odpowiedzi, ale w tej chwili nie mam wystarczającej reputacji, aby komentować i mogę jedynie sugerować zmiany. Ponieważ powyższe formularze powyżej (bez grep) zmieniają zachowanie oryginalnej odpowiedzi Dicka. Guertin, bezpośrednia edycja może i tak nie jest odpowiednia.
źródło
ls | grep mp3 | sed -n "7p" | xargs -i mplayer {}
Zauważ, że w powyższym poleceniu
xargs
będzie wywoływałmplayer
ponownie dla każdego pliku. Może to być niepożądanemplayer
, ale może być w porządku dla innych celów.źródło
mplayer
to wywołanie nowego dla każdego pliku. Ma to znaczenie, jeśli spróbujesz np .... | xargs -I{} mplayer -shuffle {}
: zagra to w całkowicie deterministycznej kolejności-shuffle
.xargs
jest najczęściej używany z poleceniami, które akceptują listę nazw plików (prosty przykładrm
:) i próbuje przekazać tyle nazw plików, ile może zmieścić się w każdym wywołaniu, w razie potrzeby dzieląc je na wiele wywołań. Możesz zobaczyć różnicę, gdy używasz polecenia, w którym widoczne jest każde wywołanie, takiego jakecho
(domyślnie):seq 0 100000 | xargs
drukuje wszystkie liczby od 0 do 23695 (specyficzne dla platformy, ale tak się dzieje w moim systemie) w pierwszym wierszu, do 45539 na linii 2 itd. I masz rację, w przypadku większości poleceń nie będzie to miało znaczenia.W systemie macOS 10.12.x (Sierra), jeśli masz spacje w nazwach plików lub podkatalogach, możesz użyć następujących opcji:
źródło
Zależy to od (a) stopnia przywiązania do liczby 7, w przeciwieństwie do, powiedzmy, cytryn i (b) tego, czy którakolwiek z twoich nazw plików zawiera znaki nowej linii (i czy chcesz zmienić ich nazwy, jeśli tak jest).
Jest na to wiele sposobów, ale niektóre z nich to:
read
Pętla nie działa, jeśli nazwy plików zawierają znaki nowej linii; pozostałe działają poprawnie nawet z nowymi liniami w nazwach (nie mówiąc już o spacjach). Za moje pieniądze, jeśli masz nazwy plików zawierające nową linię, powinieneś zmienić nazwę pliku bez nowej linii. Używanie podwójnych cudzysłowów wokół nazwy pliku jest kluczem do prawidłowego działania pętli.Jeśli masz GNU
find
i GNUxargs
(lub FreeBSD (* BSD?) Lub Mac OS X), możesz także użyć opcji-print0
i-0
, jak w:Działa to niezależnie od zawartości nazwy (jedynymi dwoma znakami, które nie mogą pojawić się w nazwie pliku, są ukośnik i NUL, a ukośnik nie powoduje problemów na ścieżce pliku, więc użycie NUL jako ogranicznika nazwy obejmuje wszystko). Jeśli jednak chcesz odfiltrować pierwsze 6 pozycji, potrzebujesz programu, który obsługuje „linie” zakończone przez NUL zamiast nowego wiersza ... i nie jestem pewien, czy istnieją.
Pierwszy jest zdecydowanie najprostszy dla konkretnego przypadku; może jednak nie uogólniać się na inne scenariusze, których jeszcze nie wymieniono.
źródło
Wiem, że nie odpowiadam
xargs
bezpośrednio na pytanie, ale warto wspomniećfind
o-exec
opcji.Biorąc pod uwagę następujący system plików:
Polecenie find można wykonać, aby obsłużyć przestrzeń w Dream Theatre i King's X. Aby znaleźć perkusistów każdego zespołu za pomocą grep:
W
-exec
opcji{}
oznacza nazwę pliku wraz ze ścieżką. Pamiętaj, że nie musisz uciekać od niego ani umieszczać go w cudzysłowie.Różnica między
-exec
terminatorami (+
i\;
) polega na tym+
, że grupuje jak najwięcej nazw plików w jednym wierszu poleceń. Natomiast\;
wykona polecenie dla każdej nazwy pliku.Tak,
find bands/ -type f -exec grep Drums {} +
spowoduje:i
find bands/ -type f -exec grep Drums {} \;
spowoduje:W takim przypadku
grep
efektem ubocznym jest wydrukowanie nazwy pliku lub nie.Oczywiście,
grep
opcje-h
i-H
będą kontrolować, czy nazwa pliku jest drukowana, niezależnie od tego, jakgrep
zostanie wywołana.xargs
xargs
może również kontrolować, jak pliki man są w wierszu poleceń.xargs
domyślnie grupuje wszystkie argumenty w jednym wierszu. Aby zrobić to samo,-exec \;
co używaxargs -l
. Zauważ, że-t
opcja nakazujexargs
wydrukowanie polecenia przed jego wykonaniem.Zobacz, że
-l
opcja mówi xargsowi, aby wykonał grep dla każdej nazwy pliku.W porównaniu do wartości domyślnej (tj. Brak
-l
opcji):xargs
ma lepszą kontrolę nad liczbą plików w wierszu poleceń. Podaj-l
opcję maksymalnej liczby plików na polecenie.Zobacz, że
grep
zostało wykonane z dwoma nazwami plików z powodu-l2
.źródło
Biorąc pod uwagę konkretny tytuł tego postu, oto moja sugestia:
Chodzi o to, aby zamienić spacje na dowolne unikalne znaki, takie jak „<”, a następnie zmienić je na „\”, odwrotny ukośnik, a następnie spację. Następnie możesz potokować to dowolne polecenie, takie jak:
Kluczem tutaj są komendy „tr” i „sed”; i możesz użyć dowolnego znaku oprócz „<”, takiego jak „?” lub nawet znak tabulacji.
źródło
tr
? Dlaczego nie tylkols *.mp3 | sed -n '7!b;s/\([[:space:]]\)/\\\1/g;p'
?Pomocne mogą być alternatywne rozwiązania ...
Możesz także dodać znak zerowy na końcu linii za pomocą Perla, a następnie użyć
-0
opcji w xargs. W przeciwieństwie do xargs -d '\ n' (w zatwierdzonej odpowiedzi) - działa to wszędzie, łącznie z OS X.Na przykład, aby rekurencyjnie wyświetlać (wykonywać, przenosić itp.) Pliki MPEG3, które mogą zawierać spacje lub inne zabawne znaki - użyłbym:
(Uwaga: Do filtrowania wolę łatwiejszą do zapamiętania składnię "| grep" niż argumenty "find's" --name).
źródło