Awk
Xargs 提取文件名
我想找到
.html
一個文件夾中的所有文件並附[file](./file.html)
加到另一個名為index.md
. 我嘗試了以下命令:ls | awk "/\.html$/" | xargs -0 -I @@ -L 1 sh -c 'echo "[${@@%.*}](./@@)" >> index.md'
但它不能
@@
在命令內部替代?我究竟做錯了什麼?注意:文件名可以包含空格等有效字元
澄清:
index.md
每一行都有[file](./file.html)
where file 是文件夾中的實際文件名
做就是了:
for f in *.html; do printf '%s\n' "[${f%.*}](./$f)"; done > index.md
當沒有文件時,使用
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
請注意,根據您使用的降價語法,如果文件名包含一些有問題的字元,您可能必須對標題部分進行 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
HTML 編碼和 URI 編碼在哪裡
%H
¹%#H
,但我們仍然需要分別處理換行符。或與
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)" }'
用於換行符
<br/>
。您可能希望使用  代替或更一般地決定不可列印字元的某種替代表示形式。您的程式碼中有幾處錯誤:
- 解析輸出
ls
$
在雙引號內使用 a表示文字awk
用於grep
可以做的事情(本身沒有錯,但是矯枉過正)xargs -0
當輸入不是 NUL 分隔時使用-I
與 衝突-L 1
。-L 1
是每行輸入執行一個命令,但將行中的每個單詞作為單獨的參數傳遞,同時-I @@
為每一行輸入執行一個命令,用整行(減去尾隨空格,並且引用仍在處理)用於替換@@
。{}
在(命令注入漏洞)的程式碼參數中使用sh
- in
sh
,var
in${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
- 替換
ls
為printf '%s\0' *
以獲取 NUL 分隔的輸出awk
使用grep -z
(GNU 擴展)來處理 NUL 分隔的輸出xargs -r0
(GNU 擴展)沒有任何-n
//-L
,-I
因為當我們生成 ash
時,我們不妨讓它處理盡可能多的文件- 已將
xargs
單詞作為額外參數傳遞給sh
(成為內聯程式碼內的位置參數),而不是在程式碼參數內。- 這意味著我們可以更輕鬆地將它們儲存在變數中(這裡
for file do
預設情況下使用 which 循環位置參數),因此我們可以使用${param%pattern}
參數擴展運算符。- 使用
printf
而不是echo
.不用說,使用它而不是像上面範例中那樣
for
直接在文件上進行循環是沒有意義的。*.html
¹它似乎不適用於我的 ksh93 版本中的多字節字元(GNU 系統上的 ksh93u+)