Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a media server with a folder called Series. (/media/Expansion2/Series/)

In it, I have (surprise!) TV series. These are just the show names, e.g., /media/Expansion2/Series/The Big Bang Theory/

Inside each show's folder (and this is where the problem lies) I have season folders. I currently have a mixture of the following 2 conventions (along with a few more, probably):

  1. /media/Expansion2/Series/The Big Bang Theory/The Big Bang Theory Season 1
  2. /media/Expansion2/Series/The Big Bang Theory/Season 2

In the end, I want to rename all folders to just Season #.

As a regex, I would probably say something like s/.*(Season \d)/$1

Only applicable to folders, not files. I should probably also mention that this is for about 50+ show sub folders, so it needs to start at the /media/Expansion2/Series/ level and look into each series :)

share|improve this question
add comment

4 Answers 4

up vote 4 down vote accepted

On Debian and derivatives (including Ubuntu):

find /media/Expansion2/Series/ -type d -exec rename -n 's/.*(Season \d)/$1/' {} ";"

The rename command is part of the Perl package. It is not provided by other distributions, they instead provide the standard Linux rename command which is not useful here.

If rename -n (-not really) displays what it wants to do, and it's all right for you, omit the -n and make it happen.

share|improve this answer
    
Must say, I've found this method particularly useful over the last few days - not only for folders, but files as well. Thanks. –  Denham Coote Apr 30 '12 at 8:24
add comment

The following snippet strips anything that occurs before the last occurrence of Season [0-9] in every show directory under /media/Expansion2/Series. No regular expressions necessary, just globs.

cd /media/Expansion2/Series
for show in ./*/; do
    (
        cd "$show" || { echo "cd failed.  Skipping $show"; exit 1; }
        for season in ./*Season\ [[:digit:]]*/; do
                season_prefix=${season%Season [[:digit:]]*}
                mv "$season" ./"${season#$season_prefix}"
        done
    )
done
share|improve this answer
add comment

If you prefer to play it safe and only rename some show/some show stuff to some show/stuff:

for d in */; do
  for f in "$d${d%/} *"; do
    mv "$f" "${d}${f%$d${d%/} }"
  done
done

If you want to strip everything before Season:

for x in */*Season*; do
  mv "$x" "${x%/*}/${x##*Season}Season"
done

${var#PATTERN} strips PATTERN at the beginning of $var and returns the result. ${var%PATTERN} does the same at the end. ${var#PATTERN} and ${var%PATTERN} remove the shortest matching prefix and suffix respectively; ${var##PATTERN} and ${var%%PATTERN} remove the longest match.

share|improve this answer
add comment

I'm going to post two more solutions in the hope that they may be helpful in future. These came from the Linux admins at work. Just goes to show how many hammers will work on this nail!

Solution 1:

Hi Denham,

I'm having to make a few assumptions here, for instance that the part of the directory with "XXX Season #" will always be the "outside" directory (leaf node).

In any case, I would write a little script. Something like this should work (note the double quotes around the variables, to ensure you capture all the spaces in the directories):

find /media/Expansion2/Series/ -type d | while read olddir
do 
   newdir=`echo "${olddir}" | awk -F "/" '$NF ~ /Season/ { last=substr($NF,index($NF, "Season")); while (i<(NF-1)) { i++; printf("/%s", $i) }; printf("/%s\n", last) } $NF !~ /Season/ { print }'`
   if [ "${olddir}" != "${newdir}" ]
   then
       mv "${olddir}" "${newdir}"
   fi
done

Of course, before you run it with the command " mv "${olddir}" "${newdir}" " you should put something like " echo "${olddir}" "${newdir}" " to ensure you're getting the results you expect or you could end up with another headache :-P


Solution 2:

Hi Denham,

Most of the answer was already in the question. Anyway running something like the following from the Series folder should work just fine:

find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "`dirname "$dir"`/`basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i"`"; done  


Explanation:
• find -mindepth 2 -maxdepth 2 -type d (list directories two levels down)
• while read dir; (loop on each dir)
• mv -T "$dir" (move the source dir to... -T is needed to get an error if the Season folders are not unique i.e. you don't have "The Big Bang Theory Season 22" and "Season 22" in the same directory)
• dirname "$dir" returns the path where the dir is
• basename "$dir" returns the name of the directory
• sed "s/.Season ([0-9])$/Season \1/i" completes the magic with case insensitive regexp, just in case.

In my small test it worked (try it first with an echo before mv):

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/The Big Bang Theory Season 1
./The Big Bang Theory/The Big Bang Theory Season 1/file1.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file 3.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file2.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file
./The Big Bang Theory/The Big Bang Theory Season 1/3.avi
./Other Series
./Other Series/Season 2
./Other Series/Stre dsfdf sd dSeason 3

someuser@linux-box:/tmp/Series$ find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "dirname "$dir"/basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i""; done
mv: ./The Big Bang Theory/Season 2' and./The Big Bang Theory/Season 2' are the same file
mv: ./Other Series/Season 2' and./Other Series/Season 2' are the same file

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/Season 1
./The Big Bang Theory/Season 1/file1.avi
./The Big Bang Theory/Season 1/file 3.avi
./The Big Bang Theory/Season 1/file2.avi
./The Big Bang Theory/Season 1/file
./The Big Bang Theory/Season 1/3.avi
./Other Series
./Other Series/Season 3
./Other Series/Season 2

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.