Я борюсь с экранированием и оценкой выражений. Я пытаюсь запустить команду внутри структуры 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'
).
Любая помощь будет оценена по достоинству. Подводя итог, цель такова:
- Рекурсивно перебрать все файлы, соответствующие
*.md
каталогу - Выполнить
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' _ {} +