Por*_*ine 4 find xargs awk echo
我想找到.html一个文件夹中的所有文件并将其附加[file](./file.html)到另一个名为index.md. 我尝试了以下命令:
ls | awk "/\.html$/" | xargs -0 -I @@ -L 1 sh -c 'echo "[${@@%.*}](./@@)" >> index.md'
Run Code Online (Sandbox Code Playgroud)
但是它不能@@在命令内部替换?我究竟做错了什么?
注意:文件名可以包含空格等有效字符
澄清:
index.md将每一行,[file](./file.html)其中文件是文件夹中的实际文件名
Sté*_*las 13
做就是了:
for f in *.html; do printf '%s\n' "[${f%.*}](./$f)"; done > index.md
Run Code Online (Sandbox Code Playgroud)
当没有文件时,使用set -o nullglob( zsh, yash) 或shopt -s nullglob( bash) for*.html扩展为空而不是*.html(或在 中报告错误zsh)html。使用zsh,您还可以使用*.html(N)或ksh93 ~(N)*.html。
或者与一个printf电话zsh:
files=(*.html)
rootnames=(${files:r})
printf '[%s](./%s)\n' ${basenames:^files} > index.md
Run Code Online (Sandbox Code Playgroud)
请注意,根据您使用的 Markdown 语法,如果文件名包含一些有问题的字符,您可能需要对标题部分进行 HTML编码并对 URI 部分进行 URI 编码。不这样做甚至可能最终根据上下文引入一种形式的 XSS 漏洞。使用 ksh93,您可以使用:
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
Run Code Online (Sandbox Code Playgroud)
其中%H¹ 进行 HTML 编码和%#HURI 编码,但我们仍然需要分别处理换行符。
或与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)"
}'
Run Code Online (Sandbox Code Playgroud)
使用<br/>的换行符。您可能想要使用 ? 取而代之或更普遍地决定不可打印字符的某种形式的替代表示。
您的代码中有几处错误:
ls$在双引号内使用意为文字awk的东西,grep可以做(没有错本身,而是矫枉过正)xargs -0时输入不是NUL分隔-I与 冲突-L 1。-L 1是为每行输入运行一个命令,但将行中的每个单词作为单独的参数传递,同时-I @@为每行输入运行一个命令,并使用整行(减去尾随空格,并且引用仍在处理)用于替换@@.{}在(命令注入漏洞)的代码参数中使用shsh,varin${var%.*}是一个变量名,它不适用于任意文本。echo任意数据。如果你想使用xargs -0,你需要这样的东西:
printf '%s\0' * | grep -z '\.html$' | xargs -r0 sh -c '
for file do
printf "%s\n" "[${file%.*}](./$file)"
done' sh > file.md
Run Code Online (Sandbox Code Playgroud)
ls用printf '%s\0' *得到NUL分隔输出awk使用grep -z(GNU 扩展)来处理以 NUL 分隔的输出xargs -r0(GNU扩展)没有任何-n/ -L/ -I,因为虽然我们在产卵sh,我们不妨把它处理尽可能多的文件成为了可能xargs单词作为额外参数传递给sh(成为内联代码内的位置参数),而不是代码参数内。for file do默认情况下使用which 循环位置参数),因此我们可以使用${param%pattern}参数扩展运算符。printf代替echo.不用说,使用它而不是像上面的例子那样for直接在*.html文件上循环是没有意义的。
¹尽管我的 ksh93 版本中的多字节字符似乎无法正常工作(GNU 系统上的 ksh93u+)
不要解析 ls。
你不需要xargs这个,你可以使用find -exec.
尝试这个,
find . -maxdepth 1 -type f -name "*.html" -exec \
sh -c 'f=$(basename "$1"); echo "[${f%.*}]($1)" >> index.md' sh {} \;
Run Code Online (Sandbox Code Playgroud)
如果您想使用xargs,请使用这个非常相似的版本:
find . -maxdepth 1 -type f -name "*.html" -print0 | \
xargs -0 -I{} sh -c 'f=$(basename "$1"); echo "[${f%.*}]($1)" >> index.md' sh {} \;
Run Code Online (Sandbox Code Playgroud)
另一种不运行xargs或的方法-exec:
find . -maxdepth 1 -type f -name "*.html" -printf '[%f](./%f)\n' \
| sed 's/\.html\]/]/' \
> index.md
Run Code Online (Sandbox Code Playgroud)