Чи можливо вкласти 'find -exec' в інший 'find -exec'?


14

Що - щось подібне до наступного, що я , що я після, але мій код не працює, незалежно від того , як я бігти {}і+ ;

find ./ -maxdepth 1 -type d -name '.*' -exec \
    find {} -maxdepth 1 -type f -name '*.ini' -exec \
        md5sum \{\} \\; \;

Після перегляду цієї Unix - & - Linux питання , я виявив , що такі роботи коду, але це не вкладеність знахідки як такі, і я підозрюю , що є кращий спосіб зробити це особливе завдання.

find ./ -maxdepth 1 -type d -name '.*' \
-exec bash -c 'for x; do
    find "$x" -maxdepth 1 -type f -name "*.ini" \
    -exec md5sum \{\} \;; \
done' _ {} \+

Чи існує якийсь спосіб гніздування find -execбез необхідності викликати шкаралупу (як вище), з усіма її хитрими цитатами та обмеженнями втечі?

Або це можна зробити безпосередньо в одній команді find, використовуючи суміш її багатьох параметрів?


4
Хоча можливо зробити те, що ви просите, коли речі стають такими складними, я перемикаюся на сценарії оболонки або Perl. Ваш другий фрагмент коду в значній мірі робить це лише за допомогою вкладеного сценарію оболонки. Героїчні однолінійки цікаві, але їх важко зрозуміти, а значить, важко підтримувати. Якщо це не одноразова угода, з якою ви все-таки якось закінчуєтесь, я не бачу вагомої причини зробити це, крім інтелектуального завдання.
Warren Young

1
@Warren Young: Я, звичайно, не думаю, що концепція є складною, але я вважаю, що ви маєте на увазі, що немає простого способу зробити це find, але якщо findне можете цього зробити, то чому findтак шанується (?) Як інструмент, використовувати для пошуку файлів? ... Я підрядчиком виявив, що find ./ -maxdepth 2 -path '.*/*.ini' -type f -exec md5sum {} \+добре працює в моїй ситуації (посилання jw013 -pruneпривело мене до цього на сторінці man), але мені цікаво, чи це надійний метод (у родах). Я ніколи не використовував find(менше ніж за рік Linux), як locateце зробив майже все, що мені потрібно, тому це невідома територія.
Пітер.O

1
-pathТест саме те , що я збирався запропонувати. З цим ви повинні мати можливість робити все, що вам завгодно (вибачте за асоціацію Ace Of Base;))
rozcietrzewiacz

Відповіді:


8

Я б спробував використати одну знахідку, наприклад:

find .*/ -maxdepth 1 -type f -name '*.ini' -execdir md5sum {} +

або навіть (зовсім ні find, просто оболонка)

md5sum .*/*.ini

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

for x in .*/*.ini; do 
    if [ -f "$x" ]; then 
        md5sum "$x"
    fi
done

що, однак, втратить перевагу лише від одного виклику md5sum.

Редагувати

Для загального та безпечного способу ланцюга findможна зробити щось подібне

find <paths> <args> -print0 | xargs -0 -I{.} find {.} <args for second find> [etc.]

Я отримую помилку з -f(f?), А потім ще одна помилка з -execdir.. Коли я замінюю -execdir на -exec та / або також замінюю md5sum на print, я нічого не отримую ..
Peter.O

Дякую, за альтернативу ... але я більше шукаю способу зробити це за допомогою find... Це не так багато, що я просто хочу, щоб цей приклад був вирішений, я шукаю розуміння способів пошуку фу-фу .. . Можливо, в пошуку більше пуху, ніж фу .. (я не знаю, тому що я його практично ніколи не використовував), і це перша ситуація, яку я дійсно хотів використати (для файлів зображень насправді) і Функція -exec, про яку я так багато чув, здається, не настільки всесильна, як її представник (?) натякає на ... (+1, хоча б на альтернативи) .. але ваш findприклад просто не працює (все одно )
Пітер.О

Я отримую цю помилку для findкоманди: ... find: The relative path ~ / bin 'входить до змінної середовища PATH, яка є небезпечною в поєднанні з дією -execdir пошуку. Видаліть цей запис із $ PATH` .... Тож, можливо, це спрацює, але я мушу сказати, що зараз я намагаюся позбутися цього ~ / bin ... Мені доведеться взяти як більше серйозно погляньте на це ... я не знаю, де я його встановив ... будь-які ідеї, де це може ховатися; the ~/binmy PATH
Peter.O

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

Гаразд .. це цікавий і хороший момент (щодо використання глобусів) ...
Пітер.О

2

Ваша початкова проблема не вимагає рекрусивного виклику, але я вважаю, що це було не в цьому.

Я вважаю, що неможливо викликати рекурсивно так, як вам потрібно.

Далі не називається пошук рекурсивно (або вкладення, як би воно не називалося), але хіба ви не можете просто взяти набір результатів першої знахідки і подати її на другий? Ось як би я інстинктивно робив:

find `find ./ -maxdepth 1 -type d -name '.*'` \
    -maxdepth 1 -type f -name '*.ini' -exec md5sum {} \;

Ви також можете використовувати xargsдля виконання другої знахідки.

Оновлення:

Я хотів би додати, що оскільки більшість утилітів UNIX беруть кілька аргументів імені файлів замість одного, зазвичай ви можете -execвзагалі уникати :

md5sum `find \`find ./ -maxdepth 1 -type d -name '.*'\` -maxdepth 1 -type f -name '*.ini'`

Коли ви вкладаєте задню панель, ви просто додаєте зворотні риски \перед внутрішніми.

Якщо ми уявляємо, що md5sumбере лише один аргумент імені файлу, ми завжди можемо обернути його у forциклі:

for f in `find \`find ./ -maxdepth 1 -type d -name '.*'\` -maxdepth 1 -type f -name '*.ini'`
do
    md5sum $f
done

Зауважте, що це стає складніше, якщо -задіяні імена файлів / директорій, що починаються з пробілу або містять його. Утиліти UNIX не грають з ними добре. В цьому випадку додавання ./, --або лапки необхідні.

Очевидно, що оригінальний приклад не є гарним, тому що ми могли просто зробити:

md5sum .*/*.ini

1
Ви дали хороший огляд ситуації, але всі показані findметоди отримують помилку, коли файл / каталог містить пробіли ... md5sum .*/*.iniПрацює чудово ... Я починаю розуміти, що * Warren Young's * коментар про те, що речі стають "складними" для того, що findтрапляється на початку гри :), але я припускаю, що він findстає своїм, коли тести стану більш складні, але що стосується гніздування -exec, я досить добре відмовився від ідеї, як здається, є простіші способи це зробити .. (але perl для мене (поки) не "простий" ...
Peter.O

0

Принаймні мені вдалося вкласти 2 команди знайти:

find ~ -maxdepth 1 -type d -name '.*' -execdir \
    find {} -maxdepth 1 -type f -name '*.ini' \;

Але я не вирішив викликати ще один -exec (dir) - дзвінок звідти.


Так, саме в цьому моя проблема :)
Peter.O

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