Batch rename sequential files by padding with zeroes

后端 未结 8 1176
天命终不由人
天命终不由人 2020-12-08 02:42

I have a bunch of files named like so:

output_1.png
output_2.png
...
output_10.png
...
output_120.png

What is the easiest way of renaming t

相关标签:
8条回答
  • 2020-12-08 02:53

    Fairly easy, although it combines a few features not immediately obvious:

    @echo off
    setlocal enableextensions enabledelayedexpansion
    rem iterate over all PNG files:
    for %%f in (*.png) do (
        rem store file name without extension
        set FileName=%%~nf
        rem strip the "output_"
        set FileName=!FileName:output_=!
        rem Add leading zeroes:
        set FileName=000!FileName!
        rem Trim to only four digits, from the end
        set FileName=!FileName:~-4!
        rem Add "output_" and extension again
        set FileName=output_!FileName!%%~xf
        rem Rename the file
        rename "%%f" "!FileName!"
    )
    

    Edit: Misread that you're not after a batch file but any solution in any language. Sorry for that. To make up for it, a PowerShell one-liner:

    gci *.png|%{rni $_ ('output_{0:0000}.png' -f +($_.basename-split'_')[1])}
    

    Stick a ?{$_.basename-match'_\d+'} in there if you have other files that do not follow that pattern.

    0 讨论(0)
  • 2020-12-08 02:56

    I actually just needed to do this on OSX. Here's the scripts I created for it - single line!

    > for i in output_*.png;do mv $i `printf output_%04d.png $(echo $i | sed 's/[^0-9]*//g')`; done
    
    0 讨论(0)
  • 2020-12-08 02:58

    Here is a Python script I wrote that pads zeroes depending on the largest number present and ignores non-numbered files in the given directory. Usage:

    python ensure_zero_padding_in_numbering_of_files.py /path/to/directory
    

    Body of script:

    import argparse
    import os
    import re
    import sys
    
    def main(cmdline):
    
        parser = argparse.ArgumentParser(
            description='Ensure zero padding in numbering of files.')
        parser.add_argument('path', type=str,
            help='path to the directory containing the files')
        args = parser.parse_args()
        path = args.path
    
        numbered = re.compile(r'(.*?)(\d+)\.(.*)')
    
        numbered_fnames = [fname for fname in os.listdir(path)
                           if numbered.search(fname)]
    
        max_digits = max(len(numbered.search(fname).group(2))
                         for fname in numbered_fnames)
    
        for fname in numbered_fnames:
            _, prefix, num, ext, _  = numbered.split(fname, maxsplit=1)
            num = num.zfill(max_digits)
            new_fname = "{}{}.{}".format(prefix, num, ext)
            if fname != new_fname:
                os.rename(os.path.join(path, fname), os.path.join(path, new_fname))
                print "Renamed {} to {}".format(fname, new_fname)
            else:
                print "{} seems fine".format(fname)
    
    if __name__ == "__main__":
        sys.exit(main(sys.argv[1:]))
    
    0 讨论(0)
  • 2020-12-08 03:01

    For mass renaming the only safe solution is mmv—it checks for collisions and allows renaming in chains and cycles, something that is beyond most scripts. Unfortunately, zero padding it ain't too hot at. A flavour:

    c:> mmv output_[0-9].png output_000#1.png
    

    Here's one workaround:

    c:> type file
    mmv
    [^0-9][0-9] #1\00#2
    [^0-9][0-9][^0-9] #1\00#2#3
    [^0-9][0-9][0-9] #1\0#2#3
    [^0-9][0-9][0-9][^0-9] #1\0#2#3
    c:> mmv <file
    
    0 讨论(0)
  • 2020-12-08 03:01

    Using ls + awk + sh:

    ls -1 | awk -F_ '{printf "%s%04d.png\n", "mv "$0" "$1"_", $2}' | sh
    

    If you want to test the command before runing it just remove the | sh

    0 讨论(0)
  • 2020-12-08 03:08

    Python

    import os
    path = '/path/to/files/'
    for filename in os.listdir(path):
        prefix, num = filename[:-4].split('_')
        num = num.zfill(4)
        new_filename = prefix + "_" + num + ".png"
        os.rename(os.path.join(path, filename), os.path.join(path, new_filename))
    

    you could compile a list of valid filenames assuming that all files that start with "output_" and end with ".png" are valid files:

    l = [(x, "output" + x[7:-4].zfill(4) + ".png") for x in os.listdir(path) if x.startswith("output_") and x.endswith(".png")]
    
    for oldname, newname in l:
        os.rename(os.path.join(path,oldname), os.path.join(path,newname))
    

    Bash

    (from: http://www.walkingrandomly.com/?p=2850)

    In other words I replace file1.png with file001.png and file20.png with file020.png and so on. Here’s how to do that in bash

    #!/bin/bash
    num=`expr match "$1" '[^0-9]*\([0-9]\+\).*'`
    paddednum=`printf "%03d" $num`
    echo ${1/$num/$paddednum}
    

    Save the above to a file called zeropad.sh and then do the following command to make it executable

    chmod +x ./zeropad.sh
    

    You can then use the zeropad.sh script as follows

    ./zeropad.sh frame1.png
    

    which will return the result

    frame001.png
    

    All that remains is to use this script to rename all of the .png files in the current directory such that they are zeropadded.

    for i in *.png;do mv $i `./zeropad.sh $i`; done
    

    Perl

    (from: Zero pad rename e.g. Image (2).jpg -> Image (002).jpg)

    use strict;
    use warnings;
    use File::Find;
    
    sub pad_left {
       my $num = shift;
    
       if ($num < 10) {
          $num = "00$num";
       }
       elsif ($num < 100) {
          $num = "0$num";
       }
    
       return $num;
    }
    
    sub new_name {
       if (/\.jpg$/) {
          my $name = $File::Find::name;
          my $new_name;
          ($new_name = $name) =~ s/^(.+\/[\w ]+\()(\d+)\)/$1 . &pad_left($2) .')'/e;
          rename($name, $new_name);
          print "$name --> $new_name\n";
       }
    }
    
    chomp(my $localdir = `pwd`);# invoke the script in the parent-directory of the
                                # image-containing sub-directories
    
    find(\&new_name, $localdir);
    

    Rename

    Also from above answer:

    rename 's/\d+/sprintf("%04d",$&)/e' *.png
    
    0 讨论(0)
提交回复
热议问题