0

I'm going to make a video of image files, but the filenames contain numbers in scientific notation, so the ordering of the name will not be correct.

The filenames are in this format:

ABC_1.000000E-01.png ~ ABC_1.100000E+01.png,
DEF_1.000000E-01.png ~ DEF_1.100000E+01.png,
GHI_1.000000E-01.png ~ GHI_1.100000E+01.png,
.
.
.

If I change the number notation used for the numbers, the order is not correct again, so I want to change it as below.

ABC_001.png ~ ABC_110.png,
DEF_001.png ~ DEF_110.png,
GHI_001.png ~ GHI_110.png,
.
.
.

How may I do this on my Linux system?

Kusalananda
  • 333,661

3 Answers3

0

Here's a script that will find every png file on the current directory and rename them accordingly. Mind that it won't overwrite existing files.


Here's the preview of the work

./DEF_1.100000E+01.png - ./DEF_11.00.png
./DEF_1.000000E-01.png - ./DEF_0.10.png
./GHI_1.000000E-01.png - ./GHI_0.10.png
./ABC_1.100000E+01.png - ./ABC_11.00.png
./GHI_1.100000E+01.png - ./GHI_11.00.png
./ABC_1.000000E-01.png - ./ABC_0.10.png

Before the script

$ ls
ABC_1.000000E-01.png  DEF_1.000000E-01.png  GHI_1.000000E-01.png  script.sh
ABC_1.100000E+01.png  DEF_1.100000E+01.png  GHI_1.100000E+01.png

After the script

$ ls
ABC_0.10.png   DEF_0.10.png   GHI_0.10.png   script.sh
ABC_11.00.png  DEF_11.00.png  GHI_11.00.png

script

#!/bin/bash

for file in $(find . -type f -name "*.png") do number=$(echo "${file}" | cut -d'_' -f 2) number=$(basename "${number}" .png) number=$(echo "${number}" | awk '{ printf("%.2f\n",$1) }')

filename=$(echo "${file}" | cut -d'_' -f 1)

mv -n "${file}" "${filename}_${number}.png"

done

otuva
  • 21
  • 1
    Don't loop over the output of find (https://unix.stackexchange.com/questions/321697). Using cut on strings is costly, just use standard parameter substitutions instead, e.g. filename=${file%%_*}. – Kusalananda Dec 17 '21 at 07:58
  • Thank you, but I just removed the exponent number and the order I wanted was not resolved. It's a problem where 10.10 ~ 11.00 are stuck between 1.00 and 1.10. – Kitae Kim Dec 21 '21 at 02:25
0

With zsh:

$ autoload -Uz zmv
$ zmv -n '(*_)(<->.<->E[+-]<->)(.png)' '$1${(l[3][0])$(( ($2*10)|0 ))}$3'
mv -- ABC_1.000000E-01.png ABC_001.png
mv -- ABC_1.100000E+01.png ABC_110.png
mv -- DEF_1.000000E-01.png DEF_001.png
mv -- DEF_1.100000E+01.png DEF_110.png
mv -- GHI_1.000000E-01.png GHI_001.png
mv -- GHI_1.100000E+01.png GHI_110.png

(and remove the -n for dry run if happy).

Similar with the perl-based variants of rename (sometimes called prename or perl-rename to disambiguate it from the (unrelated and much more limited) rename command from util-linux):

$ rename -n 's{_\K\d+\.\d+E[+-]\d+(?=\.png\Z)}{sprintf "%03d", $&*10}e' ./*.png
rename(./ABC_1.000000E-01.png, ./ABC_001.png)
rename(./ABC_1.100000E+01.png, ./ABC_110.png)
rename(./DEF_1.000000E-01.png, ./DEF_001.png)
rename(./DEF_1.100000E+01.png, ./DEF_110.png)
rename(./GHI_1.000000E-01.png, ./GHI_001.png)
rename(./GHI_1.100000E+01.png, ./GHI_110.png)

The parallel between the two:

  • perl's \d+ matches one or more decimal digits while zsh's <-> matches strings representing any decimal number (form of <x-y> without bounds), so are essentially the same.
  • sprintf "%03d" converts to integer and pads with 0. $(( number|0 )) converts to integer in zsh, while the l[3][0] does the padding.

Differences:

  • zmv will do sanity checks (such as conflicts for x_1E+2.png vs x_10E+1.png for instance or target files already there) before doing any renaming.
  • zsh's l parameter expansion flag does padding but also truncates to the specified width. So, 1.2E+3 (1200) would be truncated to 200, while sprintf "%03d" would leave it as 1200.
  • Thank you for your answer. However, it seems that zsh is not installed in the operating system. And the error '-n' occurs in the 'rename'. – Kitae Kim Dec 21 '21 at 02:26
  • @KitaeKim, -n is for dry-run like for the zmv approach. You also need one of the perl rename implementations, not the one from util-linux. – Stéphane Chazelas Dec 21 '21 at 07:50
0

Try also

ls -1 *.png | LC_ALL=C awk -F[._] '{TMP=$2 "." $3; printf "mv %s  %s_%03d.%s\n", $0, $1, 10*TMP, $4}'                  
mv ABC_1.000000E-01.png  ABC_001.png
mv ABC_1.100000E+01.png  ABC_110.png
mv DEF_1.000000E-01.png  DEF_001.png
mv DEF_1.100000E+01.png  DEF_110.png
mv GHI_1.000000E-01.png  GHI_001.png
mv GHI_1.100000E+01.png  GHI_110.png

It uses awk to isolate and convert the number in scientific notation and output its tenfold value as a zero padded integer. Pipe through e.g. sh if happy with the result.

RudiC
  • 8,969