Ubuntu – How to move files from subdirectories that have the same directory name to its relative upper/parent directory

batch-renamecommand linedirectory

So, I have a directory structure like this:

parent/
├── sub1
│   └── source
│       └── file1
│       └── file2
├── sub2
│   └── sub2.1
│       └── source
│           └── something1
│           └── something2
└── sub3
    └── sub3.1
        └── sub3.1.1
            └── source
                └── other.zip

I want to move all files (with different filename) from all directories named source to its relative upper/parent directory. So, the result should be something like this:

parent/
├── sub1
│   ├── file1
│   ├── file2
│   └── source
├── sub2
│   └── sub2.1
│       ├── something1
│       ├── something2
│       └── source
└── sub3
    └── sub3.1
        └── sub3.1.1
            ├── other.zip
            └── source

Is there an easy way (one liner) to accomplish this, maybe using the find command?
Preferably one that's not too complex for me to understand. 😀 I'm quite new to Linux.

EDIT: I'm also going to make a bash script (so I can use it easily) out of the solution. For example: ./movefiles.sh myfolder
So, preferably, the solution can easily accommodate, umm variables?, especially ones that have symbols like . (if it's a hidden directory), #, @, etc.

Best Answer

If you want a find solution, you could use this:

find parent -name "source" -type d -exec bash -c 'cd "$1"; mv * ..' bash {} \;

Explanation:

  • find parent -name "source" -type d - For each directory named source in parent...
  • -exec bash -c '...' bash {} \; - Call Bash with bash as $0 and the directory path as $1
  • cd "$1"; mv * .. - cd into the directory; move all its contents up one level.
    • Alternative: mv "$1"/* "$1/.."

This is more or less based on dessert's answer.

Including hidden files

find parent -name "source" -type d -exec bash -c 'shopt -s dotglob; cd "$1"; mv * ..' bash {} \;
  • shopt -s dotglob - Make globs include hidden files