Как использовать `find -exec` для выполнения команды в каталоге найденного файла (а не в текущем каталоге)?


15

Скажем , я нахожусь в директории , которая имеет некоторые подкаталоги dir1, dir2и dir3. У каждого из этих каталогов есть файл, fooи я хотел бы выполнить одну и ту же команду для каждого fooв каждом из каталогов, и чтобы эта команда выполнялась из этого каталога.

Если бы я делал это «вручную», это выглядело бы примерно так:

cd dir1
(execute on foo)
cd ../dir2
(execute on foo)
cd ../dir3
(execute on foo)

Обязательно, чтобы команда была выполнена из каждого из каталогов . fooявляется сценарием пакетного планирования (для HTCondor, если вы хотите знать) и должен выполняться из каждого подкаталога, чтобы вывод прогонов, запущенных сценариями планирования, попадал в каждый подкаталог.

Вопрос " Найти файл и выполнить команду в каталоге файла ", насколько я могу судить, не отвечает на мой вопрос. Первый ответ на этот вопрос - скорее обходной путь, который не будет работать в моем случае, а второй ответ не имеет достаточного объяснения, чтобы я знал, как его использовать.


@roaima, пожалуйста, объясни, как это дубликат. Первый ответ на этот вопрос мне не помогает, это скорее обходной путь, а второй ответ не имеет никакого смысла для меня. Мне нужно больше объяснений, чтобы я знал, как его использовать.
NeutronStar

Ответы:


23

Предполагая, что ваш findподдерживает его, используйте -execdirопцию вместо-exec

find * -name 'foo' -execdir pwd \;

Если это не так, пожалуйста, предоставьте информацию о вашей платформе и / или дистрибутиве (в зависимости от ситуации).


Когда вы начинаете нажимать «найти: относительный путь» ./node_modules/.bin 'включается в переменную среды PATH »: askubuntu.com/questions/621132/…
Сиро Сантилли 冠状 病毒 审查 六四 事件 法轮功

Извините, если я могу написать это так, но -execdir (в Ubuntu) - это дерьмо, потому что оно не дает вам {}, а является родителем {}.
БЛА

1
@uav, не зная вашего варианта использования, я не могу вам помочь. Но в ответ на ваше замечание в документации ясно говорится: « Нравится -exec, но указанная команда запускается из подкаталога, содержащего соответствующий файл ».
Ройма

Да, верно, это особый случай, если вы ищете -type d (= каталог), а затем он неоптимален.
БЛА

Не зная вашего варианта использования, я не могу вам помочь.
Ройма

4

Предполагая, что вы точно знаете, в каких каталогах запускается ваша команда,

for dir in dir1 dir2 dir3; do
    ( cd "$dir" && somecommand foo )
done

или, перебирая fooфайлы,

for foo in */foo; do
  ( cd "${foo%/*}" && somecommand foo )
done

Подобная оболочка предотвращает cdвлияние на рабочий каталог остальной части сценария. В ${foo%/*}подстановке параметров Раскрывается в имя каталога , в котором fooживет файл (удалив все после последней /в значении $foo).

Используя стандарт, findчтобы сделать то же самое (в случае, когда fooфайлы могут жить глубоко в структуре каталогов):

find . -type f -name foo -exec sh -c '
    for foo do
        ( cd "${foo%/*}" && somecommand foo )
    done' sh {} +

Другими словами: найдите все обычные файлы с именем «foo» в любом месте текущего каталога или ниже и укажите их пути к этому сценарию оболочки в пакетном режиме. Сценарий оболочки должен перебирать заданные пути, менять каталог на часть каталога каждого имени пути и, если это удается, выполнить somecommand foo.

Для решения, которое использует нестандартный -execdir, см . Ответ roaima . Его ответ адаптирован к моему примеру:

find . -type f -name foo -execdir somecommand foo ';'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.