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łania xargs -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

  • Godnym uwagi wyjątkiem w przenośności 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 .
  • Nie ' nie rozumiem, że -0 jest bardziej uciążliwe niż --delimiter "\n".
  • Oprócz -0, GNU xargs potrzebuje -r, aby uniknąć uruchamiania polecenia, jeśli ' nie ma żadnych danych wejściowych.
  • Innym problemem związanym z | xargs -r0 cmd jest to, że cmd ' s standardowe dotyczy (w zależności od implementacji xargs, ' s /dev/null lub potok).

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, że xargs -P nie jest w standardzie POSIX, podczas gdy find -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 zastosowania xargs; na przykład xargs 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 konstrukcja find ... -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).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *