이런 식으로 이름이 지정된 일련의 파일 이름을 바꾸고 싶습니다
name (10).ext
name (11).ext
...
도착하다
name_10.ext
name_11.ext
...
이 줄의 역할은 다음과 같습니다.
$ for i in name\ \(* ; do echo "$i" | sed -e 's! (\([0-9]\{2\}\))!_\1!' ; done
name_10.ext
name_11.ext
...
하지만 이것은 그렇지 않습니다:
$ for i in name\ \(* ; do mv "$i" "$(echo "$i" | sed -e 's! (\([0-9]\{2\}\))!_\1!')" ; done
bash: !_\1!': event not found
왜? 이 상황을 피하는 방법은 무엇입니까?
사용
$ bash --version
GNU bash, versione 4.3.48(1)-release (x86_64-pc-linux-gnu)
우분투 18.04에서.
그리고 여기유제!
!
내부 작은따옴표를 고려하고 !
내부 작은따옴표, 내부 큰따옴표와 비교하는 간단한 사례를 보여줍니다 . 주석에서 지적했듯이 Bash는 이 두 경우에 다르게 동작합니다. 이는 Bash 버전에 관한 것입니다 4.3.48(1)
. 문제는 더 이상 존재하지 않는 것 같습니다 4.4.12(1)
(그러나 경우에 따라 Bash 버전을 알 수 없으므로 이 한 줄짜리 내용은 피하는 것이 좋습니다).
Kusalananda의 답변에서 제안한 대로 sed
구분 기호를 !
로 바꾸면 #
,
$ for i in name\ \(* ; do mv "$i" "$(echo "$i" | sed -e 's# (\([0-9]\{2\}\))#_\1#')" ; done
이 문제는 전혀 발생하지 않습니다.
답변1
대화형 셸에서 사용하면 !
기록 확장이 활성화될 수 있습니다(스크립트에서는 문제가 되지 않음).
해결책은 표현식 !
외부에 다른 구분 기호를 사용하는 것입니다 sed
.
또 다른 종류의 bash
루프:
for name in "name ("*").ext"; do
if [[ "$name" =~ (.*)" ("([^\)]+)").ext" ]]; then
newname="${BASH_REMATCH[1]}_${BASH_REMATCH[2]}.ext"
printf 'Would move %s to %s\n' "$name" "$newname"
# mv -i "$name" "$newname"
fi
done
답변2
Larry Wall의 rename
명령( rename
Debian의 패키지, prename
RedHat의 패키지)을 사용할 수 있습니다. 이 명령은 (더 간단한 IMHO) Perl 정규식 구문을 사용하고 루프 코드를 작성하지 않고 args 파일을 반복합니다.
rename 's/ \(\d+\)/_$1/' name\ *
답변3
정확한 범위를 알고 있으면 다음과 같이 파일 이름을 바꿀 수 있습니다.
for i in {10..99}; do mv "name ($i).ext" "name_$i.ext"; done
또는 POSIX 전문가가 되고 싶다면:
for i in `seq 10 99`; do mv "name ($i).ext" "name_$i.ext"; done