제목 이름을 기준으로 임의의 이름을 사용하여 Markdown 파일 배치의 이름을 바꿔야 하며 대상 이름에는 공백이 있어야 합니다(이것이 표준입니다). 나는이 한 줄을 시도하고 있습니다
for i in *;
do mv $i $(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /') ;
done
하지만 이름에 공백이 포함되어 "대상 X가 디렉터리가 아닙니다."라는 오류가 발생합니다.
어떤 팁이 있나요?
답변1
주요 문제는 명령 대체가 인용되지 않아 서로 다른 매개변수로 분할되고, 각 매개변수는 경로명 확장의 대상이 되며(후자는 있지만 bash
없음 zsh
), mv
2개 이상이 보일 경우 다음과 같이 가정합니다. 마지막은 파일을 이동할 디렉터리입니다.
같은 이유로 $i
자체적으로(in) 인용해야 하며 bash
대시로 시작하는 일부 파일 이름에서 발생하는 문제를 방지하려면 대신 -
패턴에 in을 사용하거나 명령 에 닫는 마커 옵션을 넣어야 합니다 ../*
*
--
mv
또한 파일 이름을 처리하는 방식을 약간 단순화할 수 있다고 생각합니다. 첫째, sed
여러 명령을 허용할 수 있으므로 한 번만 호출하면 됩니다. 첫 번째 일치 항목뿐만 아니라 모든 일치 항목을 바꾸려면 /g
명령 끝에 추가할 수도 있습니다 . s///
또한 백슬래시 3개 중 2개는 [_\?\!\]
중복됩니다. [_?!]
을 일치시키 거나 백슬래시도 포함하려는 경우 ( 일부 유틸리티를 사용하면 더 확실하게 만들 수 있지만) 를 사용하십시오 _
.?
!
[_\?!]
[_\\?!]
for f in ./*; do
mv -- "$f" "$(grep \# "$f" | head -1 | sed -e 's/# //g' -e 's/[_?!]//g' -e's/[:/]/ - /g')"
done
또한 다음과 같이 grep
및 를 결합 할 수도 있습니다 .head
sed
for f in ./*; do
mv -- "$f" "$(sed -ne '/^# / {s///; s/[_?!]//g; s/[:/]/ - /g; p; q;}' < "$f")"
done
여기서 내부 명령은 {}
패턴에 따라 조건이 적용되고 /^# /
마지막 q
으로 스크립트가 블록 끝에서 종료되므로 일치하는 첫 번째 줄만 처리됩니다.
또한 awk
:
awk '/^# / { sub(/# /, ""); gsub(/[_?!]/, ""); gsub(/[:/]/, " - "); print; exit }' < "$f"
또한 마지막 교체를 로 변경하여 s/[:/] */ - /
이와 같은 문자열이 (대시 뒤 공백 두 개) 대신 blah: bleh
가 되도록 할 수도 있습니다.blah - blah
blah - bleh
답변2
대상 이름 주위에 따옴표를 추가하면 됩니다.
mv $i "$(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /')" ;