Search code examples
linuxrsyncmv

How to move nested files recursively


I have a folder, app, which is supposed to have import and export folders containing files like so:

$ tree
app
├── export
│   ├── some-unique-filename
│   ├── another-unique-filename
│   └── ...
└── import
    ├── some-unique-filename
    ├── another-unique-filename
    └── ...

However, due to an rsync script error (now corrected) we've ended up with the app folder being copied into itself, perhaps hundreds of times!

So right now we have this:

$ tree
app
├── app
│   ├── app
│   │   └── ... etc. 
│   ├── export
│   │   └── another-unique-filename
│   └── import
│       └── another-unique-filename
├── export
│   └── some-unique-filename
└── import
    └── some-unique-filename

How can I fix the current nested-folder structure back to the desired only-one-app folder structure?


Solution

  • A script like this should do it, from the root:

    mkdir -p new/export
    mkdir -p new/import
    
    # Or use cp - to have the option to try again if you make a mistake
    mv app/**/export/* new/export 
    mv app/**/import/* new/import
    

    The double star matches zero or more directories and subdirectories, taking care of the recursive folder structure for you.

    Dealing with deeply nested folders

    If as you say there are 100s of folders that may error, in which case an alternative is to use find with exec instead:

    mkdir -p new/export
    mkdir -p new/import
    
    # Or use cp - to have the option to try again if you make a mistake
    find app -type f -path '*/export/*' -exec mv {} $PWD/new/export/ \;
    find app -type f -path '*/import/*' -exec mv {} $PWD/new/import/ \;
    

    This finds the files recursively under the top-level app folder, and moves them to new/export and new/import (using $PWD to get an absolute path).

    Cleaning up

    Once you're happy with the results - clean up the unwanted folders:

    rm -rf app
    mv new app