대상 파일에 공백이 필요한 경우 일괄 이름 바꾸기

대상 파일에 공백이 필요한 경우 일괄 이름 바꾸기

제목 이름을 기준으로 임의의 이름을 사용하여 Markdown 파일 배치의 이름을 바꿔야 하며 대상 이름에는 공백이 있어야 합니다(이것이 표준입니다). 나는이 한 줄을 시도하고 있습니다

for i in *;
do mv $i $(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /') ; 
done

하지만 이름에 공백이 포함되어 "대상 X가 디렉터리가 아닙니다."라는 오류가 발생합니다.

어떤 팁이 있나요?

답변1

주요 문제는 명령 대체가 인용되지 않아 서로 다른 매개변수로 분할되고, 각 매개변수는 경로명 확장의 대상이 되며(후자는 있지만 bash없음 zsh), mv2개 이상이 보일 경우 다음과 같이 가정합니다. 마지막은 파일을 이동할 디렉터리입니다.

같은 이유로 $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및 를 결합 할 수도 있습니다 .headsed

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 - blahblah - bleh

답변2

대상 이름 주위에 따옴표를 추가하면 됩니다.

 mv $i "$(grep \# $i | head -1 | sed 's/# //' | sed 's/[_\?\!\]//' | sed 's/[:/]/ - /')" ; 

관련 정보