Estou lutando com a avaliação de escape e expressão. Estou tentando executar um comando dentro de uma estrutura find
... , onde opera em um arquivo e gera saída para o stdout. Para usar isso normalmente na linha de comando, simplesmente redireciono para um novo arquivo, assim:-exec COMMAND
COMMAND
COMMAND
COMMAND inputfilename.md > outputfilename.md.conf
Isso funciona bem. No entanto, se eu quiser fazer um loop recursivoTODOSos arquivos em um diretório e seu subdiretório, usando find -exec
, não consigo descobrir como separar o nome do arquivo e o caminho para poder redirecionar corretamente. Por exemplo, isso produz um erro:
find ./ *.md -not -path './/.git/*' -exec COMMAND '{} > ~/wiki/newdirectory/{}.cong' \;
porque {}
expande todo o caminho do arquivo. Eu tentei várias combinações de basename
and dirname
, mas não consigo avaliá-los (em vez disso, apenas recebo a string 'basename' etc.). Por exemplo, isso não funcionou, porque o texto 'basename' simplesmente aparece
find ./ *.md -not -path './/.git/*' -exec COMMAND '{} > ~/wiki/newdirectory/''basename {}''.conf' \;
(retorna este erro:) 'No such file or directory - .//newdirectory/README.md.conf > ~/wiki/newdirectory/basename .//newdirectory/README.md.conf'
.
Qualquer ajuda seria apreciada. Resumindo, o objetivo é:
- Iterar recursivamente todos os arquivos correspondentes
*.md
em um diretório - Execute
COMMAND inputfile.md > ~/newdirectory/inputfile.md.conf
ondeinputfile
está a mesma string em cada iteração.
Obrigado!
Responder1
Faça o que fizer, você precisará invocar um shell para realizar o redirecionamento da saída do comando para um arquivo cuja localização depende do find
resultado.
find ./ *.md -not -path './/.git/*' -exec sh -c 'COMMAND "$0" > ~/wiki/newdirectory/"${0##*/}.cong"' {} \;
Não substitua {}
dentro do shell script. Isto não é suportado em todos os sistemas, e mesmo onde é, isso não funcionaria em geral, uma vez que trataria o nome do arquivo como uma parte da sintaxe do shell, por exemplo, um arquivo chamado ;rm -rf ~;.md
faria com que você apagasse todos os seus arquivos.
${0##*/}
usa pura manipulação de string para obter o nome base do arquivo. Você também pode usar $(basename -- "$0")
.
Responder2
Se você find
aceitar -execdir
, isso deve funcionar
find . -name '*.md' -not -path './/.git/*' -execdir COMMAND {} > ~/wiki/newdirectory/{}.cong \;
Alternativamente
find . -name '*.md' -not -path './/.git/*' -exec bash -c \
'for f; do COMMAND "$f" > ~/wiki/newdirectory/"${f##*/}".cong; done' _ {} +