I have a set of filenames which are ordered numerically like:
13B12363_1B1_0.png
13B12363_1B1_1.png
13B12363_1B1_2.png
13B12363_1B1_3.png
13B12363_1B1_4.png
13B12363_1B1_5.png
13B12363_1B1_6.png
13B12363_1B1_7.png
13B12363_1B1_8.png
13B12363_1B1_9.png
13B12363_1B1_10.png
[...]
13B12363_1B1_495.png
13B12363_1B1_496.png
13B12363_1B1_497.png
13B12363_1B1_498.png
13B12363_1B1_499.png
After some postprocessing, I removed some files and I would like to update the ordering number and replace the actual number by its new position. Looking at this previous question I end up doing something like:
(1) ls -v | cat -n | while read n f; do mv -i $f ${f%%[0-9]+.png}_$n.png; done
However, this command do not recognize the "ordering number + png" and just append the new number at the end of the filename. Something like 13B12363_1B1_10.png_9.png
On the other hand, if I do:
(2) ls -v * | cat -n | while read n f; do mv $f ${f%.*}_$n.png; done
The ordering number is added without issues. Like 13B12363_1B1_10_9.png
So, for (1) it seems I am not specifying the digit
correctly but I am not able to find the correct syntax. So far I tried [0-9]
, [0-9]+
, [[:digits:]]
and [[:digits:]]+
. Which should be the proper one?
Additionally, in (2) I am wondering how I should specify rename
(CentOS version) to remove the numbers between the second and the third underscore. Here I have to say that I have some filenames like 20B12363_22_10_9.png
, so I should somehow specify second and third underscore.
3
Answers
Do not parse ls.
read
interprets and splits on IFS. bashfaq how to read a stream line by lineIn
${f%%replacement}
expansion the replacement is not regex, but globulation. Rules differ.+
means literally+
.You could
shopt -o extglob
and then${f%%+([0-9]).png}
. Or write a loop. Or match the_
too and dof=${f%%.png}; f="${f%_[0-9]*}_"
.Or something along (untested):
Another alternative, with perl:
This solution should avoid rename collisions by: first renaming files adding extra ".renamed" extension. And then removing the ".renamed" extension as the last step. Also, There are checks to detect rename collision.
Anyways, please backup your data before trying 🙂
The perl script unrolled and explained:
The regex:
Using Bash’s built-in Basic Regex Engine and a
null
delimited list of files.Tested with sample
Remove the
echo
if the result matches your expectations.Output from the sample