
Как выполнить команду, где найден файл?
Предположим, у меня есть каталог с именем testdir
, который содержит следующее:
$ ls -R testdir/
testdir/:
dir1 dir2 dir3 dir4 dir5
testdir/dir1:
doc1.pdf
testdir/dir2:
file1.txt
testdir/dir3:
doc2.pdf
testdir/dir4:
file2.txt
testdir/dir5:
doc5.pdf
Теперь я хочу выполнить действие (выполнить команду), где find
находит определенный файл/тип файла. Например, позвольте мне найти *.pdf
:
$ find . -name '*.pdf'
./testdir/dir3/doc2.pdf
./testdir/dir5/doc5.pdf
./testdir/dir1/doc1.pdf
Теперь предположим, что я хочу выполнить команду (например, скажем touch file
), где указанная выше команда находит файл(ы). Другими словами, я хочу создать файл с именем file
в каждом каталоге, где был найден хотя бы один, .pdf
так что я получаю:
$ ls -R testdir/
testdir/:
dir1 dir2 dir3 dir4 dir5
testdir/dir1:
doc1.pdf file
testdir/dir2:
file1.txt
testdir/dir3:
doc2.pdf file
testdir/dir4:
file2.txt
testdir/dir5:
doc5.pdf file
Как мне выполнить такую работу?
Может быть, для каждого найденного файла, cd
где файл существует и рекурсивно выполнить команду.
Я знаю, что это find
потрясающая функция: -exec
но я не могу заставить ее работать.
Это всего лишь пример для понимания того, что я хочу сделать. В общих чертах: как выполнить команду, в которой файл(ы) найдены (по find
) рекурсивно?
решение1
Если вы запустите эту команду, она touch file
будет запущена (возможно, несколько раз) из каталога, в котором она была запущена:
find -name '*.pdf' -exec touch file \;
С другой стороны, если запустить этот вариант, каждый экземпляр команды будет запущен в каталоге целевого файла:
find -name '*.pdf' -execdir touch file \;
В обоих случаях вы можете увидеть это в действии, заменив touch file
на echo {}
and/or pwd
.
Из страницы руководства:
-execdir command ;
-execdir command {} +
Аналогично
-exec
, но указанная команда запускается из подкаталога, содержащего соответствующий файл, который обычно не является каталогом, в котором вы запустилиfind
.
решение2
Вы можете извлечь каталог с именем файла dirname
и взять его оттуда, например так:
find . -name "*.pdf" -type f -exec bash myscript {} \;
где файл myscript
содержит следующее:
dir=$(dirname "$1")
cd "$dir"
touch file
решение3
С zsh
помощью квалификаторов glob можно выбрать, например, только .pdf
файлы и черезмодификаторысохраните имена каталогов в массиве суникальныйэлементы и затем cd
в каждый из этих каталогов и запустите свою команду. Таким образом вы запустите только свою командуодин разв каждом каталоге, независимо от количества .pdf
найденных в этом каталоге файлов:
dirlist=(**/*.pdf(.:a:h))
for d in ${(u)dirlist[@]}
(cd $d && touch file)
или
typeset -U dirlist
dirlist=(**/*.pdf(.:a:h))
for d in ${dirlist}
(cd $d && touch file)
Вы можете дополнительно комбинировать модификаторы и квалификаторы, например, для подстановки обычных файлов (скрытых и не скрытых) с расширением .bkp
и сохранения уникальных имен каталогов в массиве:
dirlist=(**/*.bkp(D.:a:h))
решение4
Не ищите дальше, просто войдите:
https://bitbucket.org/eradman/entr
Что вы можете сделать, так это позволить entr следить за указанным каталогом. Когда find найдет файл, коснитесь файла с именем, скажем, triggerfile.txt в этом каталоге и позвольте entr взять управление на себя.