I would like to rename a series of files named this way
name (10).ext
name (11).ext
...
to
name_10.ext
name_11.ext
...
This one-liner works:
$ for i in name\ \(* ; do echo "$i" | sed -e 's! (\([0-9]\{2\}\))!_\1!' ; done
name_10.ext
name_11.ext
...
But this one doesn't:
$ for i in name\ \(* ; do mv "$i" "$(echo "$i" | sed -e 's! (\([0-9]\{2\}\))!_\1!')" ; done
bash: !_\1!': event not found
Why? How to avoid this?
Using
$ bash --version
GNU bash, versione 4.3.48(1)-release (x86_64-pc-linux-gnu)
on Ubuntu 18.04.
While in this similar question a simple case with !
is shown, here a !
just inside single quotes is considered and compared to a !
inside single quotes, inside double quotes. As pointed out in the comments, Bash behaves in a different way in these two cases. This is about Bash version 4.3.48(1)
; this problem seems instead to be no more present in 4.4.12(1)
(it is however recommended to avoid this one-liner, because the Bash version may be unknown in some cases).
As suggested in the Kusalananda answer, if the sed
delimiter !
is replaced with #
,
$ for i in name\ \(* ; do mv "$i" "$(echo "$i" | sed -e 's# (\([0-9]\{2\}\))#_\1#')" ; done
this problem does not arise at all.
echo "$(echo '!foo')"
. I wonder if 4.3 is erroneously applying the "single quotes lose their special meaning inside double quotes" rule even when the former are within a command substitution? – steeldriver Nov 22 '18 at 13:11