Возможно ли вложить '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без необходимости вызывать оболочку (как указано выше) со всеми ее причудливыми ограничениями на кавычки и экранированием?

Или это можно сделать непосредственно в одной команде поиска, используя сочетание множества параметров?

Peter.O
источник
4
Хотя возможно сделать то, что вы просите, когда все становится так сложно, я переключаюсь на сценарии оболочки или Perl. Ваш второй фрагмент кода в значительной степени делает это, только с встроенным сценарием оболочки. Героические однострочники интересны, но их трудно понять и, следовательно, сложно поддерживать. Если это не однократная сделка, в которой вы, тем не менее, каким-то образом добиваетесь успеха, я не вижу веской причины для этого, кроме интеллектуального вызова.
Уоррен Янг
1
@ Уоррен Янг: Я, конечно, не думаю, что концепция сложна, но я предполагаю, что вы имеете в виду, что не существует простого способа сделать это find, но если findвы не можете этого сделать, то почему findтак почитается (?) Как инструмент использовать для поиска файлов? ... Впоследствии я обнаружил, что это find ./ -maxdepth 2 -path '.*/*.ini' -type f -exec md5sum {} \+прекрасно работает в моей ситуации (ссылка на jw013 -pruneпривела меня к этому на странице руководства), но мне интересно, является ли это надежным методом (в общем). Я никогда не использовал find(менее чем за год Linux), поскольку locateсделал почти все, что мне нужно, так что это неизвестная территория.
Peter.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.]
jw013
источник
Я получаю ошибку с -f(f?), А затем еще одну ошибку с -execdir.. Когда я заменяю -execdir на -exec и / или заменяю md5sum на print, я ничего не получаю ..
Peter.O
Спасибо за альтернативу ... но я больше о способе сделать это, используя find... Это не так много, что я просто хочу, чтобы этот пример был решен, я ищу понимание способов найти фу .. Может быть, там больше пуха, чем fu в find ... (я не знаю, потому что я практически никогда не использовал его), и это первая ситуация, в которой я действительно хотел ее использовать (для файлов изображений на самом деле) и Функция -exec, о которой я так много слышал, кажется не такой мощной, как ее rep (?), намекает на ... (+1 для альтернатив, хотя) .. но ваш findпример просто не работает (все же )
Peter.O
Я получаю эту ошибку для findкоманды: ... find: The relative path ~ / bin 'включен в переменную среды PATH, которая небезопасна в сочетании с действием -execdir команды find. Пожалуйста, удалите эту запись из $ PATH` .... Так что, возможно, это сработает, но я должен сказать, что пытался избавиться от этого ~ / bin какое-то время сейчас ... Мне нужно больше серьезный взгляд на это ... я не знаю, где я это установил ... любые идеи, где это может скрываться; ~/binв моем PATH
Peter.O
Я думаю, что сила findлучше всего ценится в ситуациях, которые не могут быть полностью выполнены с помощью шариков, но поскольку такие ситуации встречаются редко, мне обычно не нужно много искать.
jw013
Хорошо ... это интересный и хороший момент (об использовании глобусов) ...
Peter.O
2

Ваша первоначальная проблема не требует рекурсивного вызова функции find, но я полагаю, что это не главное.

Я считаю, что невозможно найти рекурсивный вызов так, как вы хотите.

Следующее также не вызывает рекурсивный вызов (или вложение, как бы оно ни называлось), но разве вы не можете просто взять набор результатов первого поиска и передать его второму? Вот как я бы инстинктивно поступил:

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Работает нормально ... Я начинаю понимать, что * Уоррен Янг * комментарий о том, что вещи становятся «сложными», 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. :)
пользователь неизвестен