Разделите имя файла и путь внутри опции -exec команды find

Разделите имя файла и путь внутри опции -exec команды find

Я борюсь с экранированием и оценкой выражений. Я пытаюсь запустить команду внутри структуры find... -exec COMMAND, где COMMANDработает с одним файлом и выводит на stdout. Чтобы использовать это COMMANDв командной строке обычным образом, я просто перенаправляю в новый файл, например:

COMMAND inputfilename.md > outputfilename.md.conf

Это работает отлично. Однако, если я хочу рекурсивно пройтись поВСЕфайлы в каталоге и его подкаталоге, используя find -exec, я не могу понять, как разделить имя файла и путь, чтобы можно было правильно перенаправить. Например, это приводит к ошибке:

find ./ *.md -not -path './/.git/*' -exec COMMAND '{} > ~/wiki/newdirectory/{}.cong' \;

потому что {}расширяет весь путь к файлу. Я пробовал различные комбинации basenameи dirname, но, похоже, не могу заставить их оценить (вместо этого я просто получаю строку 'basename' и т. д.). Например, это не сработало, потому что текст 'basename' просто отображается

find ./ *.md -not -path './/.git/*' -exec COMMAND  '{} > ~/wiki/newdirectory/''basename {}''.conf' \;

(возвращает эту ошибку: 'No such file or directory - .//newdirectory/README.md.conf > ~/wiki/newdirectory/basename .//newdirectory/README.md.conf').

Любая помощь будет оценена по достоинству. Подводя итог, цель такова:

  1. Рекурсивно перебрать все файлы, соответствующие *.mdкаталогу
  2. Выполнить COMMAND inputfile.md > ~/newdirectory/inputfile.md.conf, где inputfileв каждой итерации одна и та же строка.

Спасибо!

решение1

Что бы вы ни делали, вам потребуется вызвать оболочку для перенаправления вывода команды в файл, местоположение которого зависит от результата find.

find ./ *.md -not -path './/.git/*' -exec sh -c 'COMMAND "$0" > ~/wiki/newdirectory/"${0##*/}.cong"' {} \;

Не заменяйте {}внутри скрипта оболочки. Это поддерживается не во всех системах, и даже там, где это поддерживается, это не будет работать в общем случае, поскольку это будет рассматривать имя файла как часть синтаксиса оболочки, например, файл с именем ;rm -rf ~;.mdприведет к удалению всех ваших файлов.

${0##*/}использует чистую манипуляцию строками для получения базового имени файла. Вы также можете использовать $(basename -- "$0").

решение2

Если вы findсогласны -execdir, это должно сработать.

find . -name '*.md' -not -path './/.git/*' -execdir COMMAND {} > ~/wiki/newdirectory/{}.cong \;

Поочередно

find . -name '*.md' -not -path './/.git/*' -exec bash -c \
'for f; do COMMAND "$f" > ~/wiki/newdirectory/"${f##*/}".cong; done' _ {} +

Связанный контент