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
awk
para algo quegrep
pode fazer (não errado, mas exagerado) - use
xargs -0
quando a entrada não for delimitada por NUL -
-I
está 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
, ovar
em${var%.*}
é um nome da variável , não funcionará com texto arbitrário. - use
echo
para 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
ls
porprintf '%s
para obter uma saída delimitada por NULawk
' * -
grep -z
comxargs -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
sh
passando 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
echo
em 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)