Basta fazer:
for f in *.html; do printf '%s\n' "[${f%.*}](./$f)"; done > index.md
Use set -o nullglob ( zsh , yash ) ou shopt -s nullglob ( bash ) para *.html para expandir para nada em vez de *.html (ou relatar um erro em zsh ) quando houver nenhum arquivo html . Com zsh , você também pode usar *.html(N) ou ksh93 ~(N)*.html .
Ou com uma chamada printf com zsh :
files=(*.html)
rootnames=(${files:r})
printf '[%s](./%s)\n' ${basenames:^files} > index.md
Observe que, dependendo da sintaxe de marcação que você está usando, talvez seja necessário codificar em HTML a parte título e codificar em URI a parte URI se os nomes de arquivo contiverem alguns caracteres problemáticos. Não fazê-lo pode até acabar introduzindo uma forma de vulnerabilidade XSS dependendo do contexto. Com o ksh93, você pode fazer isso com:
for f in *.html; do
title=${ printf %H "${file%.*}"; }
title=${title//$'\n'/"<br/>"}
uri=${ printf '%#H' "$file"; }
uri=${uri//$'\n'/%0A}
printf '%s\n' "[$title]($uri)"
done > index.md
Em que %H ¹ faz a codificação HTML e %#H da codificação URI, mas ainda precisamos abordar os caracteres de nova linha separadamente.
Ou com perl :
perl -MURI::Encode=uri_encode -MHTML::Entities -CLSA -le '
for (<*.html>) {
$uri = uri_encode("./$_");
s/\.html\z//;
$_ = encode_entities $_;
s:\n:<br/>:g;
print "[$_]($uri)"
}'
Usando <br/> para caracteres de nova linha. Você pode preferir usar  ou, em geral, decidir sobre alguma forma de representação alternativa para caracteres não imprimíveis.
Existem algumas coisas erradas no seu código:
- analisando a saída de
ls - use
$para ser literal entre aspas duplas - Usando
awkpara algo quegreppode fazer (não errado, mas exagerado) - use
xargs -0quando a entrada não for delimitada por NUL -
-Iestá em conflito com-L 1.-L 1é executar um comando por linha de entrada, mas com cada palavra na linha passada como argumentos separados, enquanto-I @@executa um comando para cada linha de entrada com a linha completa (menos os espaços à direita e citando ainda processados ) usado para substituir@@. - usando
{}dentro do argumento código desh( vulnerabilidade de injeção de comando ) - Em
sh, ovarem${var%.*}é um nome da variável , não funcionará com texto arbitrário. - use
echopara dados arbitrários.
Se você quiser usar xargs -0 , precisará de algo como:
printf '%sfor f in *.html; do printf '%s\n' "[${f%.*}](./$f)"; done > index.md
' * | grep -z '\.html$' | xargs -r0 sh -c '
for file do
printf "%s\n" "[${file%.*}](./$file)"
done' sh > file.md
- Substituindo
lsporprintf '%spara obter uma saída delimitada por NULawk' * -
grep -zcomxargs -r0(extensão GNU) para processar essa saída delimitada por NUL -
-n(extensões GNU) sem qualquer-L/-I/sh, porque enquanto estamos gerando umxargs, também podemos processá-lo com o maior número possível de arquivos - tem
shpassando as palavras como argumentos extras parafor file do(que se tornam os parâmetros posicionais dentro do código embutido), não dentro do argumento de código. / li> - o que significa que podemos armazená-los mais facilmente em variáveis (aqui com
${param%pattern}, que faz um loop sobre os parâmetros posicionais por padrão) para que possamos usar o operador de expansão de parâmetroprintf. - use
echoem vez defor.
Não é preciso dizer que faz pouco sentido usar isso em vez de fazer esse *.html loop diretamente sobre os arquivos %code% , como no exemplo acima.
¹ Parece que não funciona corretamente para caracteres multibyte na minha versão do ksh93 (ksh93u + em um sistema GNU)