After trying to reorganize my movie folder on my Debian machine, I ended up with a structure like this:

├── Universal.Love(2017)(1080p)
│   └── Universal.Love(2017)(1080p)
│       └── Universal.Love(2017)(1080p)
│           └── Universal.Love(2017)(1080p).mkv
│               └── Universal.Love(2017)(1080p).mkv.mkv
├── Unknown.User.2014.German.DTS.DL.1080p.BluRay.x264-EXQUiSiTE
│   └── exq-unknownuser-1080p
│       └── exq-unknownuser-1080p
│           └── exq-unknownuser-1080p
│               └── exq-unknownuser-1080p.mkv
├── Unsane.2018.1080p.BluRay.x264-DRONES
│   └── Unsane.2018.1080p.BluRay.x264-DRONES
│       └── Unsane.2018.1080p.BluRay.x264-DRONES
│           └── Unsane.2018.1080p.BluRay.x264-DRONES
│               └── Unsane.2018.1080p.BluRay.x264-DRONES.mkv
├── Untitled (2017)
│   └── Untitled.2017.WEBDL-1080p
│       └── Untitled.2017.WEBDL-1080p
│           └── Untitled.2017.WEBDL-1080p
│               └── Untitled.2017.WEBDL-1080p.mkv

Is there a possibility to only end up with the .mkv inside ONE subfolder

  • How should the subfolder and the file be named? Should it be foo/foo.mkv or foo.mkv/foo.mkv.mkv or foo/foo.mkv.mkv?
    – mosvy
    Apr 21, 2020 at 9:41

3 Answers 3

shopt -s globstar nullglob
for dir in ./*/; do
    for file in "$dir"/**/*.mkv; do
        [ ! -f "$file" ] && continue
        mv -i "$file" "$dir"

The above double loop would solve your issue.

It does this by iterating over the directories in the current directory (which is supposed to be the directory that holds all those top-level directories). For each directory, all .mkv files from anywhere below that directory are moved up into the subdirectory. This is done by means of the ** glob in bash which matches recursively into subdirectories.

The globstar shell option is enabled to enable the use of **, and nullglob is also enabled so that the loops don't run at all if there are no matches of the given patterns.

You may then delete empty directories with

find . -type d -empty -delete

Try this,

find . -mindepth 3 -type f -name "*.mkv" -exec sh -c '
    f="$1"; IFS=/ && set -- $f; echo mv -t "$2" "$f"
' find-sh {} \;

(How to find the first subfolder: via)

Remove the echo when you checked the output.
This will move all *.mkv files that are deeper than 2 levels in the structure to the first subdirectory of your current dir.

Then you might want to remove the empty directories:

find . -type d -empty -delete

Try this,

find . -maxdepth 1 -type d ! -name '.' | while read -r folder; do
        find $folder -type f -name '*.mkv' -exec mv {} $folder \;
        find $folder -type d -empty -delete
  • 1st find will get all the primary directories list.
  • 2nd find will move the available .mkv file to the primary directory.
  • 3rd find will delete all empty directories inside the primary directory.

Note: we can also move the 3rd find out of while loop to delete all empty directories in one shot.

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.