bash script to rename multiple directories

Hello

I have a directory structure with year in format 4 digits, e.g 2009, below which is month format 1 or 2 digits, e.g 1 or 12, blow which is day format 1 or 2 digits, e.g 1 or 31.

I want to change the names of lots of directories to the be
Year - 4 digits , e.g 2009 - No change here
Month 4 digi year, underscore, 2 digit month - e.g 2009_10 for October 2009
Day 4 digi year, underscore, 2 digit month, underscore, 2 digit day - e.g 2009_10_31 for 31st October 2009

Some files already have the new naming structure so there must be a check before renaming somehow. there are files within the day directories which should be unchanged.

So far I thought to use the find -d command to check for directories and check for directories named with only a single character and place a zero at the start of the name.

How do I check how many characters are in the directory name?

And after that I got kind of lost......any bored script writers out there?

Thanks in advance people

Show some sample input, and expected output, as there is some confusions in your explanation.

I'm assuming you have something like this:

2009  # year dir
    # month dir
  -  1
  -  2
        # days
      - 01  # already partly correct
      - 02
      - 3
      - 2009_02_04  #fully correct
      ...
  -  3
  - 2009_04
   -05

If you can assume that anything with a "_" is already fully correct, you don't have to test for length.

I'd do this in Perl. Something like

#!/usr/bin/perl
foreach(<200*>) {
  $year=$_;
  opendir(YEAR,$year);
  while(defined($month=readdir(YEAR))) {
     next if $month =~ /^\./;
     next if $month =~ /_/;
     opendir(MONTH, "$year/$month") ;
     while(defined($day=readdir(MONTH))) {
        next if $day =~ /^\./;
        next if $day =~ /_/;
        $newname=sprintf("%d_%0.2d_%0.2d",$year,$month,$day);
        print " --  $year $month $day is $year/$month/$newname\n"; 
        # rename "$year/$month/$day", "$year/$month/$newname";
     }
     
     $newname=sprintf("%d_%0.2d",$year,$month);
     print "$year $month is $year/$newname\n"; 
     # rename "$year/$month", "$year/$newname";
    
  }
}

I wrote this to be obvious rather than clever. If I've misunderstood your directory structure, of course this won't be right, but you can modify it.

When you are satisfied this will do what you want, uncomment the rename lines.

Tony

The perl script you wrote does almost exactly as wanted, it's just the rename command that does not work with no error message.

Can't seem to see why, I've opened up permissions etc but no luck.

Any ideas?

Thanks

Anyone interested here is my script.

#!/bin/bash
cd ~/tst2
## set variable year_dir as first year
year_dir=2007

## checks dir exists and is a directory and into FIRST LOOP
while [ -d "$year_dir" ] && [ "$year_dir" -le 2010 ]
do
cd $year_dir
YEAR=`basename $PWD` ;echo "YEAR IS "$YEAR
## list all directories and into SECOND LOOP
for month_dir in `ls -d *`
do
cd $month_dir
MONTH=`basename $PWD | awk '{printf "%02i",substr($0,length($0)-1)}'` ;echo "MONTH IS "$MONTH
## lists all single char directories,i.e. 1 to 9 and into THIRD LOOP
for day_dir_1char in `ls -d [1-9]`
do
echo "mv "$day_dir_1char" 0"$day_dir_1char
mv $day_dir_1char 0$day_dir_1char
done
## exit THIRD LOOP
## list all two char dirs and rename all days (all in 2 char format). in to FOURTH LOOP
for day_dir_2char in `ls -d [0-3][0-9]`
do
echo "mv $day_dir_2char to "$YEAR"_"$MONTH"_"$day_dir_2char
mv $day_dir_2char $YEAR\_$MONTH\_$day_dir_2char
done
## exit FOUTH LOOP
cd ..
echo "mv $month_dir to "$YEAR""$MONTH
mv $month_dir $YEAR\
$MONTH
# echo "cmv "$month_dir $YEAR"_"$MONTH
# DAY=`basename $PWD`; echo "DAY IS "$DAY
done
let year_dir=$year_dir+1
cd ..
done