Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 254
  • Last Modified:

Script to rename a file based on its directory structure

Hello,

I have hundreds of image files in multiple directories that I would like to rename. Essentially, I want to prepend the directory structure to the filename and leave the file in its original directory. I would also like it to log the changes that it makes to a single logfile. Please let me know if there is anything that I need to clarify.


As an example:

/dir1
   |-dir2
       |-image-001.jpg
       |-image-002.jpg


would become:
dir1_dir2_image-001.jpg
dir1_dir2_image-002.jpg


and the logfile would show:
image-001.jpg  dir1_dir2_image-001.jpg
image-002.jpg  dir1_dir2_image-002.jpg
0
austerhaus
Asked:
austerhaus
1 Solution
 
TintinCommented:
Much better/easier with a shell script

#!/bin/sh
LOG=/path/to/logfile

for file in `find /dir1 -name "*.jpg"`
do
  newfile=`echo $file|sed 's#/#_#g'`
  mv $file `dirname $file`/$newfile && echo "`basename $file` $newfile" >>$LOG
done
0
 
Adam314Commented:
>>Much better/easier with a shell script
as long as you are on unix   :)

Basically the same code in perl:
#!/usr/bin/perl
use File::Find;
$LOG=/path/to/logfile

find(\&ProcessFile, "/dir1");

sub ProcessFile {
    return if $File::Find::name !~ /\.jpg/i;    #skip any non-jpg files
    return if !-f $File::Find::name;               #skip any non-files (eg: directories)
   
    $newfile=$File::Find::name;
    $newfile =~ s#/#_#g;
    rename $File::Find::name, $File::Find::dir . "/" . $newfile
   
    open(LG, ">>$LOG") or die "Couln't open log: $!\n";
    print LG $File::Find::name . ", " . $File::Find::dir . "/" . $newfile . "\n";
    close(LG);
}
0
 
austerhausAuthor Commented:
Thasnks for the reply. Is there a way to modify this so that I am not required to manually specify the directory path? Basically, I would prefer if it simply prepended the directory structure from where the script is run down to the location of the file. I know my initial post sorta mucked up the the intention. I hope this is clearer:

A better example:
/root
   |home
      |dir1      
         |-dir2
             |-image-001.jpg
             |-image-002.jpg


would become:
dir1_dir2_image-001.jpg
dir1_dir2_image-002.jpg

...when I run the script from the home directory.


To get it to work, I had to change:

#!/bin/sh
LOG=logfile.txt
for file in `find /home/user/temp/test -name "*.jpg"`
do
  newfile=`echo $file|sed 's#/#_#g'`
  mv $file `dirname $file`/$newfile && echo "`basename $file` $newfile" >>$LOG
done

This gives me the following results:
_home_user_temp_test_dir2_images_image-001.jpg

when I started with this:
images_image-001.jpg
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
ozoCommented:
cd $HOME
perl -MFile::Find -e 'find({no_chdir=>1,wanted=>sub{/\.jpg$/and($newfile=$_)=~s#(?<\!^.)/#_#g&&(rename $_,$newfile or warn "$newfile $!")&&print "$newfile\n"}},".")' >> logfile.txt

0
 
TintinCommented:
If you want it to run from your current directory, simple do:

#!/bin/sh
LOG=logfile.txt
HERE=`pwd`

for file in `find $HERE -name "*.jpg"`
do
  newfile=`echo $file|sed -e "s#$HERE/##" -e 's#/#_#g'`
  mv $file `dirname $file`/$newfile && echo "`basename $file` $newfile" >>$LOG
done
0
 
austerhausAuthor Commented:
Great. Thank you for the assistance Tintin.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now