chase
chase

Reputation: 3782

One liner shell script to reorganize files by date

I have a folder with a lot of files named by date like this:

(Some numbers)-date-(somenumbers).filet ype

Where 'date' is listed like:

20150730225001 For July 30, 2015 at 0 10:50 (and 1 second)

Is there a quick way to organize this with the Ubuntu terminal to give a structure like this:

Current folder/year/month/day/hour/ (all files fitting criteria to be placed here)

I have tried looking for a solution to this but most have just confused me since I'm pretty new to Unix scripting.

Upvotes: 0

Views: 83

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84559

The solution presumes you are using bash as your shell on Ubuntu and that you have all of the files you wish to organize in the current working directory. While not a one liner, you can accomplish what you are attempting with a few lines using string indexes to separate the various components of the date into year, month, day and hour relatively easily. Then using mkdir -p to check/create the needed relative path and mv to move the file to the new destination. A couple of compound commands can be added to provide a few sanity checks to insure you have a 14-digit date/time string, etc.

There are a number of ways to approach the separation (e.g. date -d, etc.), but simple string indexes are probably the most efficient. Let me know if you have questions:

A semi-one-liner with continuations

for i in *; do dt=${i%-*}; dt=${dt#*-}; [ ${#dt} -eq 14 ] || continue; \
y=${dt:0:4}; mo=${dt:4:2}; d=${dt:6:2}; h=${dt:8:2}; \
mkdir -p "$y/$mo/$d/$h" && mv "$i" "$y/$mo/$d/$h" || \
printf "error: unable to create: '%s'\n" "$y/$mo/$d/$h"; done

formatted

#!/bin/bash

for i in *; do 

    dt=${i%-*}      ## separate date string from filename
    dt=${dt#*-}

    [ ${#dt} -eq 14 ] || continue  ## validate 14 chars

    y=${dt:0:4}     ## separate into year, mo, day, hour
    mo=${dt:4:2}    #  (you can add checks for ranges)
    d=${dt:6:2}
    h=${dt:8:2}

    ## create new dir & move or throw error
    mkdir -p "$y/$mo/$d/$h" && mv "$i" "$y/$mo/$d/$h" || \
    printf "error: unable to create: '%s'\n" "$y/$mo/$d/$h"

done

Upvotes: 1

nowox
nowox

Reputation: 29096

So with these two files inside foo/

42-20150730225001-473826.filet
98-20141115180001-482157.filet

You can either use this Perl script:

#!/usr/bin/perl
for(@ARGV) {
   if (/.*-(\d{4})(\d\d)(\d\d)(\d+)-.*[.]filet/) {
       `mkdir -p $1/$2/$3/ && mv $_ $1/$2/$3/$4.filet`;
   }
}

or this oneliner:

ls | xargs perl -e 'for(@ARGV){qx{mkdir -p $1/$2/$3/ && mv $_ $1/$2/$3/$4.filet} if /.*-(\d{4})(\d\d)(\d\d)(\d+)-.*[.]filet/}'

Upvotes: 2

Related Questions