Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a directory like this


And I would like this



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
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
                except OSError:
share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .