Для каждого соответствующего файла (т. Е. Каждого каталога) findпереключается на каталог, в котором он находится (т. Е. Его родительский каталог), и выполняет указанную команду. Поскольку команда не использует имя совпадения, она никогда не будет действовать на все каталоги. Для этого конкретного дерева каталогов вы делаете
(cd . && touch foo) # because ./a matches
(cd ./a && touch foo) # because ./a/b matches
(cd ./a/b && touch foo) # because ./a/b/c matches
Чтобы создать файл в каждом каталоге, вы можете просто использовать -execвместо -execdir, при условии, что ваша реализация findдопускает {}внутри аргумента (большинство делают, и, в частности, я думаю, все):
find . -type d -exec touch {}/foo +
Для переносимости POSIX вам необходимо выполнить сборку имени каталога и базового имени файла вручную.
find . -type d -exec sh -c 'touch "$0/foo"' {} \;
или (немного быстрее)
find . -type d -exec sh -c 'for d; do touch "$d/foo"; done' _ {} +
Кроме того, вы можете использовать рекурсивное сопоставление с подстановочными знаками в bash. Помните, что (в отличие от соответствующей функции в ksh и zsh и в отличие от вашей findкоманды) bash рекурсивно используется по символическим ссылкам на каталоги.
shopt -s globstar
for d in **/*/; do touch -- "$d/foo"; done
Zsh решение:
touch ./**/(e\''REPLY+=foo'\')
man bashсостояния в «-c»: аргументы после command_string назначаются позиционным параметрам, начинающимся с $ 0, однако «для d» будет перебирать позиционные параметры, начинающиеся с $ 1. «_» - это текст, который назначен на $ 0 и не будет использоваться.