Andrew Nguyen
Andrew Nguyen

Reputation: 33

Recursively find a directory and rename it in Shell Script

Im putting together a simple Shell script to run on a Linux Machine where I would:

1) Look for specific sub-directories within a main directory. These sub-dirs have a very specific naming convention (see below) and they are always 2 -max depth below the main directory.

2) Rename those sub-dirs to PART of its original name.

For example, The sub directories are named:

andrew-11111
andrew-11112
andrew-11113
andrew-11114

The path to get to these sub dirs would look something like this:

myphotos/sailing/photos/andrew-1111
myphotos/sailing/photos/andrew-1112
myphotos/biking/photos/andrew-1113
myphotos/hiking/photos/andrew-1114

Id like take out the 'andrew-' from each of these sub dirs:

myphotos/sailing/photos/1111
myphotos/sailing/photos/1112
myphotos/biking/photos/1113
myphotos/hiking/photos/1114

Ive gotten as far as "finding" the sub dirs and listing them. I also understand how to copy and rename in command line. But putting it together at my level of shell scripting knowledge has been taking much more time than I can afford. Just a disclaimer, I am more than willing to learn, and have written a handful of shell scripts, but still new to this. Any help or examples are much appreciated!

Upvotes: 2

Views: 446

Answers (2)

Barmar
Barmar

Reputation: 780724

Use wildcards to match the files in the nested directories

You can use bash parameter expansion operators to manipulate the filenames.

for file in myphotos/*/photos/*; do
    name=${file##*/}    # remove everything up to last /
    dir=${file%/*}      # remove everything from last /
    newname=${name##*-} # remove everything up to last -
    mv "$file" "$dir/$newname"
done

If you have the perl-based rename command, you can do:

rename 's#[^/]*-##' myphotos/*/photos/*

Upvotes: 5

fancyPants
fancyPants

Reputation: 51868

You can do it with this one-liner:

find -type d -name andrew\* -exec sh -c 'mv {} $(dirname {})/$(basename {} | cut -d"-" -f2)' \;

Explanation:

  • -type d find only directories
  • -name andrew\* self-explaining, you have to escape the * though
  • -exec sh -c '...' execute it in a subshell, so you can do the command substitution ($(...)) without problems
  • mv {} the {} holds whatever find finds
  • dirname gives you the path to a directory (try it out with a random path, my english is too bad now to explain better)
  • basename gives you the last directory of a given path
  • cut -d"-" -f2 use cut to cut off "andrew-". For this set the delimiter to - and select the field number 2

Upvotes: 3

Related Questions