Search code examples
linuxcommand-line-interfacerenamearchlinuxfile-management

Renaming Sequentially Named Files with Date Embedded


The Situation:

I have hundreds of zip files with an arbitrary date/time mixed into its name (4-6-2021 12-34-09 AM.zip). I need to get all of these files in order such that (0.zip, 1.zip 2.zip etc) with in a Linux cli system.

What I've tried:

I've tried ls -tr | while read i; do n=$((n+1)); mv -- "$i" "$(printf '%03d' "$n").zip"; done which almost does what I want but still seems to be out of order (I think its taking the order of when the file was created rather than the filename (which is what I need)).

If I can get this done, my next step would be to rename the file (yes a single file) in each zip to the name of the zip file. I'm not sure how I'd go about this either.

tl;dr

I have these files named with a weird date system. I need the date to be in order and renamed sequentially like 0.zip 1.zip 2.zip etc. It's 3:00 AM and I don't know why I'm up still trying to solve this and I have no idea how I'll rename the files in the zips to that sequential number (read above for more detail on this).

Thanks in advance!


Solution

  • GNU awk is an option here, redirecting the result of the file listing back into awk:

    awk '{ 
            fil=$0;                                          # Set a variable fil to the line
            gsub("-"," ",$1);                                # Replace "-" for " " in the first space delimited field
            split($1,map," ");                               # Split the first field into the array map, using " " as the delimiter
            if (length(map[1])==1) { 
              map[1]="0"map[1]                               # If the length of the day is 1, pad out with "0"
            };
            if (length(map[2])==1) { 
              map[2]="0"map[2]                               # Do the same for month
            }
            $1=map[1]" "map[2]" "map[3];                     # Rebuilt first field based on array values
            gsub("-"," ",$2);                                # Change "-" for " " in time
            map1[mktime($1" "$2)]=fil                        # Get epoch format of date/time using mktime function and use this as an index for array map1 with the original line (fil) as the value
         } 
     END { 
            PROCINFO["sorted_in"]="@ind_num_asc";            # At the end of processing, set the array sorting to index number ascending
            cnt=0;                                           # Initialise a cnt variable
            for (i in map1) { 
               print "mv \""map1[i]"\" \""cnt".zip\"";       # Loop through map1 array printing values and using these values along with cnt to generate and print move command
               cnt++ 
            } 
          }' <(for fil in *AM.zip;do echo $fil;done)
    

    Once you are happy with the way the print command are printed, pipe the result into bash and so:

    awk '{ fil=$0;gsub("-"," ",$1);split($1,map," ");if (length(map[1])==1) { map[1]="0"map[1] };if (length(map[2])==1) { map[2]="0"map[2] }$1=map[1]" "map[2]" "map[3];gsub("-"," ",$2);map1[mktime($1" "$2)]=fil} END { PROCINFO["sorted_in"]="@ind_num_asc";cnt=0;for (i in map1) { print "mv \""map1[i]"\" \""cnt".zip\"";cnt++ } }' <(for fil in *AM.zip;do echo $fil;done) | bash