I have inherited a folder structure on a project and would like to simplify it a bit. I have a root full of folders (1st level) and each of those folders has a number of folders in it (2nd level) and each of those folders has a some files inside. It looks something like this:

|-- dir1
|    |-- dir1.1
|    |      +- file1.txt
|    |-- dir1.2
|    |     +- file2.txt
|    +-- dir1.N
|          +- fileN.txt
|-- dir2
|    |-- dir2.1
|          +- file3.txt
|-- dir3
|    |-- dir3.1
|          +- file4.txt


I'd like to remove all of the x.1 folders, simplify the structure, and move all the files from those folders one level down:

|-- dir1
|     +- file1.txt
|     +- file2.txt
|     +- fileN.txt
|-- dir2
|     +- file3.txt
|-- dir3
|     +- file4.txt

How would I go about accomplishing something like this through bash/zsh?

  • There is a Unix and Linux Stack Exchange site where you might get more answers. – WindowsEscapist Dec 20 '12 at 2:54
  • 1
    @WindowsEscapist: Yes, but shell scripting questions are welcome here, and they are often answered quickly and/or correctly. – Scott Dec 20 '12 at 3:33
  • @user1064903: wouldn't that be "one level up"? – akira Dec 20 '12 at 5:59
  • Well, Hi user. Please don't drop "user signature" everywhere. Your user card could be improved for doing that. It follows you everywhere. And, the "Thanks" won't be required while asking question. Instead, you could use "thanks" after getting the answer :-) – Waffle's Crazy Peanut Dec 20 '12 at 6:10
  • @Scott I know, I'm just making a pre-emptive suggestion (plus the site needs a little attention IMO). – WindowsEscapist Dec 20 '12 at 15:11

I don’t know whether this will work in zsh, but I expect that it will in bash (although I haven’t fully tested it):

for f in */*/*
        mv "$f" "$(dirname "$(dirname "$f")")"

for f in */*
        if [ –d "$f" ]
                rmdir "$f"

P.S. In Unix (unlike botany; i.e., the real world), trees have their roots at the top.  Therefore, this operation would be considered moving files up the directory structure.

  • Thank you! That worked perfectly even though I got a bunch of "line 9: [: –d: unary operator expected" which is the "if [ -d "$f" ]" line. – user1064903 Dec 20 '12 at 3:55
  • @user1064903: Interesting. Maybe if [[ –d "$f" ]] will work, but I would have expected either to be acceptable. – Scott Dec 20 '12 at 17:08
for d in */*; do
    mv "$d"/* "$d"/..
    rm -r "$d"

This doesn't work if the second level contains empty directories or files.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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