.html
폴더에서 모든 파일을 찾아 [file](./file.html)
다음 명령을 index.md
시도했습니다.
ls | awk "/\.html$/" | xargs -0 -I @@ -L 1 sh -c 'echo "[${@@%.*}](./@@)" >> index.md'
@@
그런데 명령 내에서는 바꿀 수 없나요 ? 내가 뭘 잘못했나요?
참고: 파일 이름에는 공백과 같은 유효한 문자가 포함될 수 있습니다.
밝히다:
index.md
각 줄의 file은 [file](./file.html)
폴더의 실제 파일 이름입니다.
답변1
그냥 해:
for f in *.html; do printf '%s\n' "[${f%.*}](./$f)"; done > index.md
파일이 없는 경우 set -o nullglob
( zsh
, yash
) 또는 shopt -s nullglob
( bash
)를 사용하여 *.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
사용하는 Markdown 구문에 따라 다음이 필요할 수 있습니다.제목파일 이름에 문제가 있는 문자가 포함되어 있으면 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
여기서 %H
¹는 HTML 인코딩과 %#H
URI 인코딩을 수행하지만 여전히 개행 문자를 별도로 처리해야 합니다.
또는 다음을 사용하여 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
(명령 주입 취약점)- 지금
sh
,var
지금${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
- NUL로 구분된 출력을 얻으려면
ls
다음으로 바꾸십시오 .printf '%s\0' *
awk
(GNU 확장)을 사용하여grep -z
NUL로 구분된 출력 처리xargs -r0
-n
(GNU 확장) // 없이-L
,-I
생성할 때sh
가능한 한 많은 파일을 처리하도록 할 수 있기 때문입니다.xargs
으로 전달 된 단어추가의매개변수sh
(가위치 매개변수인라인 코드 내), 코드 매개변수 내가 아닙니다.- 즉, 변수에 더 쉽게 저장할 수 있으므로(
for file do
여기서는 위치 인수가 기본적으로 반복됨)${param%pattern}
인수 확산 연산자를 사용할 수 있습니다. printf
대신 사용하십시오echo
.
말할 필요도 없이 위의 예처럼 for
파일을 직접 반복하는 대신 이것을 사용하는 것은 의미가 없습니다 .*.html
1 그러나 내 ksh93 버전(GNU 시스템의 ksh93u+)에서는 멀티바이트 문자를 올바르게 처리하지 못하는 것 같습니다.
답변2
ls를 구문 분석하지 마세요. 이것은
필요하지 않습니다 . xargs
를 사용하면 됩니다 find -exec
.
이 시도,
find . -maxdepth 1 -type f -name "*.html" -exec \
sh -c 'f=$(basename "$1"); echo "[${f%.*}]($1)" >> index.md' sh {} \;
만약 너라면생각하다를 사용하려면 xargs
다음과 매우 유사한 버전을 사용하세요.
find . -maxdepth 1 -type f -name "*.html" -print0 | \
xargs -0 -I{} sh -c 'f=$(basename "$1"); echo "[${f%.*}]($1)" >> index.md' sh {} \;
실행하지 않고 다른 xargs
방법 또는 -exec
:
find . -maxdepth 1 -type f -name "*.html" -printf '[%f](./%f)\n' \
| sed 's/\.html\]/]/' \
> index.md
답변3
정말로 필요합니까 xargs
?
ls *.html | perl -pe 's/.html\n//;$_="[$_](./$_.html)\n"'
(파일이 100,000개 이상인 경우):
printf "%s\n" *.html | perl -pe 's/.html\n//;$_="[$_](./$_.html)\n"'
또는 (느리지만 더 짧음):
for f in *.html; do echo "[${f%.*}](./$f)"; done