знайти -exec + vs знайти | xargs: яку вибрати?


32

Я розумію, що -execможе прийняти +варіант імітувати поведінку xargs. Чи є якась ситуація, коли ви віддасте перевагу одній формі над іншою?

Особисто я віддаю перевагу першій формі, хоча б лише уникати використання труби. Думаю, безумовно, розробники, напевно, findзробили відповідні оптимізації. Я прав?

Відповіді:


21

Можливо, вам захочеться ланцюжкові дзвінки, щоб знайти (колись ви дізналися, що це можливо, що може бути сьогодні). Це, звичайно, можливо лише до тих пір, поки ви залишаєтеся в пошуку. Після того, як ви перейдете до xargs, це буде поза межами сфери.

Невеликий приклад, два файли a.lst і b.lst:

cat a.lst
fuddel.sh
fiddel.sh

cat b.lst
fuddel.sh

Тут немає жодної хитрості - просто той факт, що обидва містять "фуддел", а лише один містить "фідель".

Припустимо, ми цього не знали. Ми шукаємо файл, який відповідає 2 умовам:

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

Ну, можливо, ви знаєте, що синтаксис grep чи інша програма передають обидва рядки як умову, але це не в цьому суть. Тут можна використовувати будь-яку програму, яка може повернути істинне чи помилкове, якщо файл є аргументом - grep був просто популярним прикладом.

І зауважте, ви можете слідувати find -exec з іншими командами знаходження, наприклад -ls або -delete або чимось подібним. Зауважте, що видалення робить не тільки rm (видаляє файли), але і rmdir (видаляє каталоги).

Такий ланцюг читається як комбінація команд AND, якщо інше не вказано (а саме з -orперемикачем (і паронами (які потребують маскування)).

Таким чином, ви не залишаєте ланцюжок пошуку, що є зручною річчю. Я не бачу жодної переваги у використанні -xargs, оскільки вам потрібно бути обережними при передачі файлів, що щось не потрібно робити - це автоматично обробляє передачу кожного файлу як єдиний аргумент для вас.

Якщо ви вважаєте, що вам потрібно замаскувати знахідки {} брекетів , не соромтесь відвідати моє запитання, яке вимагає підтвердження. Моє твердження: Ви цього не робите.


3
Цей пост відкрив мені очі на новий спосіб використання find. Дуже дякую!
rahmu

1
"Я не бачу жодної переваги у використанні -xargs". Який -execспосіб зробити xargs -P4так, щоб три з чотирьох ядер не залишалися без роботи?
Даміан Єррік

1
@DamianYerrick: Завершіть команду -exec не на ";" але зі знаком + (/ плюс).
користувач невідомий

25

Безпечне передавання імен файлів xargsвимагає, щоб ваша опція findпідтримувала, -print0а у вашого xargsбула відповідна опція для читання ( --nullабо -0). В іншому випадку назви файлів з недрукованими символами або зворотними косими рисами чи котируваннями або пробілами у назві можуть спричинити несподівану поведінку. З іншого боку, find -exec {} +є в специфікації POSIXfind , тому він є портативним, і він настільки ж безпечний find -print0 | xargs -0, і, безумовно, безпечніший find | xargs. Я рекомендував би ніколи не робити find | xargsбез -print0.


6
Помітним винятком портативності find … -exec … {} +є OpenBSD, який придбав цю функцію лише у версії 5.1, випущеній у 2012 році. Усі BSD були -print0протягом декількох років, навіть OpenBSD (хоч вона і деякий час протистояла цій функції). Solaris, з іншого боку, дотримується функцій POSIX, тому ви отримуєте -exec +і ні -print0.
Жил 'ТАК - перестань бути злим'

-print0це біль, і хоча ви можете стверджувати, що xargs --delimiter "\n"це не рівнозначно, я ніколи не користувався першим після виявлення другого.
Шрідхар Сарнобат

3
Я не бачу, як -0біль більше, ніж біль --delimiter "\n".
jw013

2
Крім цього -0, GNU xargsпотрібно -rуникати виконання команди, якщо немає вводу.
Стефан Шазелас

2
Ще одна проблема | xargs -r0 cmdполягає в тому cmd, що на це впливає stdin (залежно від xargsреалізації, це /dev/nullчи труба.
Stéphane Chazelas

10

Якщо ви використовуєте -exec ... ;форму (пам'ятаючи про те, щоб уникнути крапки з комою), ви виконуєте команду один раз на ім’я файлу. Якщо ви використовуєте -print0 | xargs -0, ви запускаєте кілька команд на ім’я файлу. Ви обов'язково повинні використовувати -exec +форму, яка розміщує кілька файлів в одному командному рядку і набагато швидше, коли задіяна велика кількість файлів.

Великий плюс використання xargs- це можливість паралельно використовувати декілька команд паралельно xargs -P. На багатоядерних системах це може забезпечити величезну економію часу.


6
Ви мали на увазі -Pзамість цього -p. Майте на увазі, що xargs -Pце не є стандартом POSIX, тоді як find -exec {} +є, що важливо, якщо ви збираєтесь переносити.
jw013

@ Алексіос Вам не потрібно уникати знаку плюс, оскільки він не має особливого значення для оболонки: find /tmp/ -exec ls "{}" +працює просто чудово.
daniel kullmann

1
Корента, звичайно. Я так довго втікав від усього після цього -exec(я мазохіст, я навіть не використовую цитати, щоб втекти {}, я завжди набираю \{\}; не запитуй), все схоже, що зараз його слід уникати .
Олексій

1
@ Алексіос: Якщо ви знайдете приклад (за винятком того, що є мазохістом), де маскування брекетів є корисним, будь ласка, надайте це як відповідь на моє запитання тут . Я ніколи не бачив приклад, де find /tmp/ -exec ls {} +не працювало б.
користувач невідомий

1
Для мене це м'язова пам’ять, сформована в часи SunOS 4. Оскільки я це роблю роками, я абсолютно не помітила, коли bashпочала приймати дужки дословно. Я впевнений, що принаймні одна зі старих оболонок, яку я використав, кинула шипучі приступи, якщо брекети не уникнули.
Алексіос

8

Щодо продуктивності, я вважав, що це -exec … +буде просто краще, оскільки це єдиний інструмент, який виконує всю роботу, але частина документації GNU findutil говорить про те, що -exec … +в деяких випадках це може бути менш ефективно:

[знайти з -exec … +] може бути менш ефективним, ніж деякі використання xargs; наприклад, xargsдозволяє створювати нові командні рядки, поки виконується попередня команда, і дозволяє задавати кількість команд для виконання паралельно. Однак find ... -exec ... +конструкція має перевагу в широкій портативності. Додаткові виплати GNU не підтримували " -exec ... +" до версії 4.2.12 [січня 2005] ; Однією з причин цього є те, що він вже мав -print0дію в будь-якому випадку.

Я не був точно впевнений, що це означає, тому я запитав у чаті, де Дероберт пояснив це як:

findможливо, можна продовжувати пошук наступної партії файлів під час -exec … +запуску, але це не так.
find … | xargs …так, бо тоді пошук - це інший процес, і він продовжує працювати, поки буфер труб не заповниться

(Форматування мною.)

Так що це є. Але якщо продуктивність дійсно важлива, вам доведеться зробити реалістичний бенчмаркінг, а точніше навіть запитати себе, чи хочете ви навіть використовувати оболонку для таких випадків.

Тут, на цьому веб-сайті, я думаю, що краще порадити людям користуватися -exec … +формою, коли це можливо, тому що просто тому, що це простіше і з причин, зазначених в інших відповідях тут (наприклад, обробка дивних назви файлів, не потребуючи багато думати).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.