Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a directory like this

root/A/b/SomeFile.jpg
root/A/B/OtherFIle.jpg
root/a/D/yet_again.jpg

And I would like this

root/a/b/somefile.jpg
root/a/b/otherfile.jpg
root/a/d/yet_again.jpg

OR

other_root/a/b ...

I'm happy with assuming that there aren't collisions.

How could I do this in a bash or python script (or something prebuilt to sort files and directories)?

I'd do by hand, but there are thousands of them.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

Obligatory zsh solution:

for x in root/**/*(On); do mv -i $x ${x:h}/${x:t:l}; done

This will ask for confirmation in case of a collision.

Explanation: ** means all (sub)*directories, recursively. (On) sorts in decreasing lexicographic order, so that directories always turn up after their contents. ${x:h} means the directory name part of $x, ${x:t} means its base name, and the :l converts to lowercase.

Bash 4 might be able to do it, since it has **, but I don't know if it has an equivalent of (On).

share|improve this answer
    
Wow, cool one-(ish) liner. But two (or one and a half) issues. 1) the OP wants to normalize the dir names too. I don't know zsh but i'm assuming: mv -i $x ${x:h:l}/${x:t:l} would work. And at this point, you may need to create the subdirs. [ ! -d ${x:h:l} ] && mkdir -p ${x:h:l} –  Rich Homolka Aug 23 '10 at 22:36
    
@Rich: **/*(On) matches directories too, so they will be downcased. And because of (On), directories are downcased after their contents, which is why the mv command is careful not to lowercase the directory part. –  Gilles Aug 23 '10 at 23:09

Here is a very specific, non-general way to solve this problem, which I'd call 'brute force' at best.

import os
import re
import shutil

path = os.getcwd()
newpath = os.path.join(path,'..','newpics')
for item in os.listdir(path):
    path1 = os.path.join(path,item)
    if os.path.isdir(path1):
        for item_2 in os.listdir(path1):
            path2 = os.path.join(path1,item_2)
            for item_3 in os.listdir(path2):
                path3 = os.path.join(path2,item_3)
                item_lc = item.lower()
                item_2lc = item_2.lower()
                item_3lc = item_3.lower()
                pic_path = os.path.join(newpath,item_lc,item_2lc,item_3lc)
                print os.path.join(path,item,item_2,item_3)
                print pic_path
                try:
                    os.makedirs(os.path.join(newpath,item_lc,item_2lc))
                except OSError:
                    pass
                shutil.copyfile(path3,pic_path)
share|improve this answer

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.