Reputation: 377
I've got a folder full of files with the names ab1234, abc5678, etc., and I want to switch them to abc3412, abc7856, etc. – just swap the last two characters out with the second-to-last two characters. The filenames are all in this format, no surprises. What's the easiest way to do this with a regex?
Upvotes: 0
Views: 91
Reputation: 438093
Depending on your platform, you may have a rename
utility that can directly do what you want.
For instance, anishsane's answer shows an elegant option using a Perl-based renaming utility.
Here's a POSIX-compliant way to do it:
printf '"%s"\n' * | sed 'p; s/\(..\)\(..\)"$/\2\1"/' | xargs -L 2 mv
printf '"%s"\n' *
prints all files in the current folder line by line (if there are subdirs., you'd have to exclude them), enclosed in literal double-quotes.sed 'p; s/\(..\)\(..\)"$/\2\1"/'
produces 2 output lines:
p
prints the input line as-is.s/\(..\)\(..\)"$/\2\1"/'
matches the last 2 character pairs (before the closing "
) on the input lines and swaps them.xargs -L 2 mv
then reads pairs of input lines (-L 2
) and invokes the mv
utility with each line as its own argument, which results in the desired renaming. Having each line enclosed in double-quotes ensures that xargs
treats them as a single argument, even if they should contain whitespace.Tip of the hat to anishsane for the enclose-in-literal-double-quotes approach, which makes the solution robust.
Note: If you're willing to use non-POSIX features, you can simplify the command as follows, to bypass the need for extra quoting:
GNU xargs
:
printf '%s\n' * | sed 'p; s/\(..\)\(..\)$/\2\1/' | xargs -d '\n' -L 2 mv
Nonstandard option -d '\n'
tells xargs
to not perform word splitting on lines and treat each line as a single argument.
BSD xargs
(also works with GNU xargs
):
printf '%s\n' * | sed 'p; s/\(..\)\(..\)$/\2\1/' | tr '\n' '\0' | xargs -0 -L 2 mv
tr '\n' '\0'
replaces newlines with \0
(NUL) chars, which is then specified as the input-line separator char. for xargs
with the nonstandard -0
option, again ensuring that each input line is treated as a single argument.
Upvotes: 2