Як використовувати `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/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Вибачте, якщо я можу написати це так, але -execdir (на Ubuntu) - це лайно, тому що воно дає не вам {}, а батькові {}.
uav

1
@uav, не знаючи вашого випадку використання, я не можу вам допомогти. Але у відповідь на ваш whinging документація чітко вказує " Like -exec, але вказана команда запускається з підкаталогу, що містить відповідний файл ".
roaima

Так, правильно, це особливий випадок, якщо ви шукаєте -type d (= каталог), і тоді він є оптимальним.
uav

Не знаючи вашого випадку використання, я не можу вам допомогти.
roaima

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.