0

I have bunch of directories such as

2013_03_12_18_26_am
2013_03_12_18_26_cu
2013_03_12_18_26_ig
2013_03_12_18_26_mdf
2013_03_12_18_26_pih
2013_03_12_18_26_tn
2013_03_12_18_26_an
2013_03_12_18_26_cv
2013_03_12_18_26_ik
2013_03_12_18_26_mhr
2013_03_12_18_26_pnb    
2013_03_12_18_26_to

What I want to do is rename them to their last two characters, example: 2013_03_12_18_26_am to am, I know I can do this one by one mv 2013_03_12_18_26_am am but that would take a long time. Can this be accomplis from the shell script?

I want everything after the last "_" to be the name of the new directory.

add-semi-colons
  • 18,094
  • 55
  • 145
  • 232

5 Answers5

3

I noticed that those dir-names have no spaces, or other special chars. so you could try:

ls|xargs -n1 |sed -r 's/(.*_)(.*)/mv & \2/'

to print mv cmd for you. if you think all commands are correct, then you just pipe it to |sh

note, ls part you could change to get only those dirs.

Kent
  • 189,393
  • 32
  • 233
  • 301
  • This is my kind of solution. A one-liner that uses all the right unix tools. – Jon Cairns Mar 21 '13 at 17:18
  • @JonathanCairns personally I feel like xargs and sed if overkill in this case, when there are perfectly good built-ins to do the job, but to each his own. – cmh Mar 21 '13 at 17:44
  • @cmh you're right, it's just preference, but I find it a real pain trying to use bash constructs from the command line (trying to get semicolons in the right place, for instance). As long as it gets the job done though... – Jon Cairns Mar 21 '13 at 17:48
  • @cmh I feel it is not so bad... It is of course possible that save that xargs, and use `ls -l` and longer sed line (or shorter awk line) to print the `mv a b`... take a look those shellscripts in our real life. this is not "overkill", there are so many `grep|awk|sed|awk|cut|sort|awk...` :) – Kent Mar 21 '13 at 21:06
  • @Kent Sure, it's not going to kill any servers. It just seems needless to spawn `n+2` procs when you can achieve this just using builtins. – cmh Mar 22 '13 at 10:21
2

If all directories following the above form then in bash you can use the following variable subsitituion to extract the characters after the final _

var=2013_03_12_18_26_am
echo ${var##*_} #am

You can then rename all directories in the folder with:

for dir in *_*; do #as there may be more than 2 chars after final _
    new_dir=${dir##*_}
    mv $dir $new_dir
done

Of course you will want to add checks to make sure you are only moving directories and that you aren't overwriting anything.

cmh
  • 10,612
  • 5
  • 30
  • 40
1
 for d in *_??
 do
     newd=$(expr $d : '.*_\([a-z][a-z]*\)')
     mv $d $newd
 done
suspectus
  • 16,548
  • 8
  • 49
  • 57
1

This assume all (and only all) of your folders are in one directory. So be careful...

Original:

marks-mac-pro:test mstanislav$ ls
2013_03_12_18_26_am 2013_03_12_18_26_an 2013_03_12_18_26_cu 2013_03_12_18_26_cv     2013_03_12_18_26_ig 2013_03_12_18_26_ik 2013_03_12_18_26_mdf    2013_03_12_18_26_mhr    2013_03_12_18_26_pih    2013_03_12_18_26_pnb    2013_03_12_18_26_tn 2013_03_12_18_26_to

Shell Script:

marks-mac-pro:test mstanislav$ for i in `ls .`; do NEW=`echo $i | cut -d_ -f6`; mv $i $NEW; done

Result:

marks-mac-pro:test mstanislav$ ls
am  an  cu  cv  ig  ik  mdf mhr pih pnb tn  to

Please test this before doing it on the real data, just to make sure. Again, only do this in a directory with JUST the folders you want to rename, or re-write the first part for the ls to be more specific.

Mark Stanislav
  • 979
  • 4
  • 11
0

I like the rename command for this, which allows perl regexp like so:

rename 's/.*([a-z]{2})$/$1/' *
ezeedub
  • 103
  • 1
  • 11