Rozumiem, że -exec
może przyjąć opcję +
naśladować zachowanie xargs
. Czy jest jakaś sytuacja, w której wolałbyś jedną formę od drugiej?
Osobiście wolę pierwszą formę, choćby po to, by uniknąć używania potoku. Na pewno twórcy find
musi” wykonać odpowiednią optymalizację. Czy mam rację?
Odpowiedź
Możesz połączyć połączenia w łańcuch, aby znaleźć (gdy już się dowiedziałeś, że jest to możliwe , co może być dzisiaj). Jest to oczywiście możliwe tylko wtedy, gdy pozostajesz w znalezieniu. Gdy potokujesz do xargs, jest poza zakresem.
Mały przykład, dwa pliki a.lst i b.lst:
cat a.lst fuddel.sh fiddel.sh cat b.lst fuddel.sh
Żadnej sztuczki – po prostu fakt, że oba zawierają słowo „fuddel”, ale tylko jeden zawiera słowo „fiddel”.
Załóżmy, że o tym nie wiedzieliśmy. Szukamy pliku spełniającego 2 warunki:
find -exec grep -q fuddel {} ";" -exec grep -q fiddel {} ";" -ls 192097 4 -rw-r--r-- 1 stefan stefan 20 Jun 27 17:05 ./a.lst
Cóż, może znasz składnię grepa lub innego programu, który przekazuje oba ciągi jako warunek, ale to ” Nie o to chodzi. Każdy program, który może zwrócić prawdę lub fałsz, podając plik jako argument, może zostać tutaj użyty – grep był tylko popularnym przykładem.
I zauważ, że możesz śledzić find -exec z innymi poleceniami wyszukiwania, takimi jak -ls lub -delete lub coś podobnego. Pamiętaj, że usunięcie nie tylko robi rm (usuwa pliki), ale rmdir (usuwa katalogi).
Taki łańcuch jest odczytywany jako kombinacja poleceń AND, o ile nie określono inaczej (mianowicie z przełącznikiem -or
(i parens (które wymagają maskowania))).
Więc nie opuszczasz łańcucha wyszukiwania, co jest bardzo przydatne. Nie widzę żadnej korzyści w używaniu -xargs, ponieważ musisz uważać przy przekazywaniu plików, co jest czymś, czego find nie musi robić – automatycznie obsługuje przekazywanie każdego pliku jako pojedynczego argumentu.
Jeśli uważasz, że potrzebujesz maskowania dla znalezionych {} nawiasów klamrowych , zapraszam do odwiedzenia mojego pytania, które wymaga dowodów. Moje twierdzenie jest następujące: Nie „t.
Komentarze
- Ten post otworzył mi oczy na nowy sposób korzystania z
find
. Wielkie dzięki! - ” Nie ' nie widzę żadnej korzyści z używania -xargs „. Jaki ' jest
-exec
sposób działaniaxargs -P4
tak, aby trzy z czterech rdzeni nie ' nie pozostawały bezczynne? - @DamianYerrick: Zakończ polecenie -exec nie w „; ” ale ze znakiem + (/ plus).
Odpowiedź
Bezpieczne przesyłanie nazw plików do xargs
wymaga, aby find
obsługiwał -print0
, a xargs
ma odpowiednią opcję, aby ją przeczytać (--null
lub -0
). W przeciwnym razie nazwy plików zawierają unprintab znaki le, ukośniki odwrotne, cudzysłowy lub spacje w nazwie mogą powodować nieoczekiwane zachowanie. Z drugiej strony find -exec {} +
jest w POSIX find
specyfikacji , więc jest przenośny i mniej więcej tak samo bezpieczny jak find -print0 | xargs -0
i zdecydowanie bezpieczniejszy niż find | xargs
. Nie radzę nigdy robić find | xargs
bez -print0
.
Komentarze
Odpowiedź
Jeśli korzystasz z formularza -exec ... ;
(pamiętając aby uniknąć średnika), „uruchamiasz polecenie raz na nazwę pliku. Jeśli używasz -print0 | xargs -0
, uruchamiasz wiele poleceń na nazwę pliku. Zdecydowanie powinieneś użyć -exec +
, który umieszcza wiele plików w jednym wierszu poleceń i jest znacznie szybszy w przypadku dużej liczby plików.
Duży plus użycia xargs
to możliwość równoległego uruchamiania wielu poleceń przy użyciu xargs -P
. W systemach wielordzeniowych, co może zapewnić ogromną oszczędność czasu.
Komentarze
- Miałeś na myśli
-P
zamiast-p
. Pamiętaj, żexargs -P
nie jest w standardzie POSIX, podczas gdyfind -exec {} +
jest, co jest ważne, jeśli chcesz przenosić. - @Alexios Nie ' nie musisz uciekać przed znakiem plus, ponieważ nie ma on specjalnego znaczenia dla powłoki:
find /tmp/ -exec ls "{}" +
działa dobrze. - Oczywiście, Corrent. Od tak dawna ' unikałem wszystkiego po
-exec
(ja ' mam masochista , Nie ' nie używam nawet cudzysłowów, aby uciec{}
, zawsze piszę\{\}
; nie ' nie pytaj), wszystko wygląda na to, że musi zostać teraz zmienione. - @Alexios: Jeśli znajdziesz przykład (oprócz bycia masochistą), maskowanie szelek jest przydatne, proszę podać je jako odpowiedź na moje pytanie – afaik ta wskazówka jest nieaktualna i tylko relikt na stronie podręcznika. ' nigdy nie widziałem przykładu, w którym
find /tmp/ -exec ls {} +
nie działałoby '. - Dla mnie jest to pamięć mięśniowa utworzona w czasach SunOS 4. Odkąd ' robię to od lat, zupełnie nie zauważyłem, kiedy
bash
zaczął dosłownie akceptować nawiasy klamrowe. ' Jestem całkiem pewien, że przynajmniej jedna ze starych powłok, których ' użyłem, była pasująca, jeśli szelki były ' t ucieczki.
Odpowiedź
Jeśli chodzi o wydajność, pomyślałem, że byłoby po prostu lepsze, ponieważ „jest to jedno narzędzie wykonujące całą pracę, ale część dokumentacji GNU findutil mówi, że -exec … +
może być mniej wydajne w niektórych przypadkach:
[znajdź za pomocą
-exec … +
] może być mniej wydajne niż niektóre zastosowaniaxargs
; na przykładxargs
umożliwia tworzenie nowych wierszy poleceń, podczas gdy poprzednie polecenie jest nadal wykonywane, i pozwala określić liczbę poleceń, które mają być wykonywane równolegle. Jednak konstrukcjafind ... -exec ... +
ma tę zaletę, że jest bardzo przenośna. GNU findutils nie obsługiwał „-exec ... +
” aż do wersji 4.2.12 [styczeń 2005] ; jedną z przyczyn takiego stanu rzeczy jest to, że w każdym przypadku miało już działanie „-print0
”.
Nie byłem pewien, co to znaczy, więc zapytałem na czacie, gdzie derobert wyjaśnił to następująco:
find
prawdopodobnie mógłby kontynuować wyszukiwanie następnej partii plików, podczas gdy-exec … +
działa, ale nie „t.
find … | xargs …
działa, ponieważ wtedy znajdowanie jest innym procesem i zachowuje działa, aż bufor potoku się zapełni.
(Formatowanie przeze mnie.)
Więc to jest to. Ale jeśli wydajność naprawdę ma znaczenie, musiałbyś przeprowadzić realistyczne testy porównawcze, a nawet zadać sobie pytanie, czy w ogóle chciałbyś używać powłoki w takich przypadkach.
W tej witrynie myślę, że lepiej jest doradzić ludziom używaj formularza -exec … +
kiedy tylko jest to możliwe, ponieważ tylko dlatego, że jest prostszy i z powodów wymienionych w innych odpowiedziach tutaj (np. obsługa dziwnych nazw plików bez konieczności zbytniego myślenia).
find … -exec … {} +
jest OpenBSD, który uzyskał tę funkcję dopiero w wersji 5.1 wydanej w 2012 roku. Wszystkie BSD miały-print0
przez kilka lat, nawet OpenBSD (choć przez pewien czas opierał się tej funkcji). Z drugiej strony Solaris trzyma się funkcji POSIX, więc otrzymujesz-exec +
i nie-print0
.-print0
jest uciążliwe i chociaż można się kłócićxargs --delimiter "\n"
nie jest ' t równoważne, ' nigdy nie użyłem pierwszego po odkryciu drugiego .-0
jest bardziej uciążliwe niż--delimiter "\n"
.-0
, GNUxargs
potrzebuje-r
, aby uniknąć uruchamiania polecenia, jeśli ' nie ma żadnych danych wejściowych.| xargs -r0 cmd
jest to, żecmd
' s standardowe dotyczy (w zależności od implementacjixargs
, ' s/dev/null
lub potok).