Nome de arquivo e caminho separados dentro da opção -exec do comando find

2

Estou lutando com a avaliação de escape e expressão. Eu estou tentando executar um comando dentro de um find ... -exec COMMAND estrutura, onde COMMAND opera em um arquivo e saídas para o stdout. Para usar este COMMAND normalmente na linha de comando, eu simplesmente redireciono para um novo arquivo, assim:

COMMAND inputfilename.md > outputfilename.md.conf

Isso funciona bem. No entanto, se eu quiser fazer um loop recursivo sobre ALL os 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 que Posso 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 e dirname , mas não consigo obtê-los para avaliar (em vez disso, eu só pegar a string 'basename' etc.). Por exemplo, isso não funcionou, porque o texto 'basename' é exibido

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. Para resumir, o objetivo é:

  1. Faça uma iteração recursiva sobre todos os arquivos correspondentes a *.md em um diretório
  2. Execute COMMAND inputfile.md > ~/newdirectory/inputfile.md.conf , em que inputfile é a mesma sequência em cada iteração.

Obrigado!

    
por jbeldock 08.01.2015 / 21:38

2 respostas

5

Não importa o que você faça, você precisará invocar um shell para executar o redirecionamento da saída do comando para um arquivo cuja localização dependa do resultado find .

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

Não substitua {} no script de shell. Isto não é suportado em todos os sistemas e, mesmo onde está, isso não funcionaria em geral, uma vez que trataria o nome do ficheiro como uma parte da sintaxe da shell, e. um arquivo chamado ;rm -rf ~;.md faria com que você apagasse todos os seus arquivos.

${0##*/} usa manipulação pura de strings para obter o nome base do arquivo. Você também pode usar $(basename -- "$0") .

    
por 09.01.2015 / 01:04
1

Se o seu find aceitar -execdir , isso deve funcionar

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

Alternadamente

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

Tags