0

I have a directory tree containing photos & videos, where I've "tagged" some information via the path. What I'd like to do is move all folders of a specific name into a separate folder, but reproduce the paths leading up to each instance of folders of that name. For example, starting with:

/Media
.../Pics
....../Travel
........./Round-The-World1
........./Round-The-World2
............./Japan
............./Europe
................/Italy
................/Spain
....../Home
.../Vids
....../Travel
........./Round-The-World1
........./Round-The-World2
............./Japan
............./Europe
................/Italy
................/Spain
....../Home

Let's say I wanted to move the folders with the exact name "Europe" (i.e. not with "Europe" as a substring - only folders that are named "Europe," and their children). The desired result:

/Media
.../Pics
....../Travel
........./Round-The-World1
........./Round-The-World2
............./Japan
....../Home
.../Vids
....../Travel
........./Round-The-World1
........./Round-The-World2
............./Japan
....../Home

/New
.../Pics
....../Travel
........./Round-The-World2
............./Europe
................/Italy
................/Spain
.../Vids
....../Travel
........./Round-The-World2
............./Europe
................/Italy
................/Spain

It's somewhat similar to Extract files with specific file extension and keep directory structure?, but I'm quite a beginner with the Linux cli, and don't want to risk screwing up my organization - so any help would be appreciated :)

1 Answer 1

1

One thing you need to take into consideration before looking at the following answer is that you will effectively be recreating the whole path all the way from /

This will be a multi-step process, because you are looking to recreate the parent folder structure, and not precisely copy it and its contents. The structure is as follows

home/
├── fol_a
│   ├── fol_ABC
│   │   └── My Folder
│   │       └── file 2
│   └── fol_XYZ
│       └── My Folder
│           ├── file1
│           └── fol_extra
│               └── file 3
└── my test
   
11 directories, 3 files

in other words the full path of file1 is /home/fol_a/fol_XYZ/My Folder/file1. Our goal is to move folders My Folder and their contents, to the my test folder such that their paths become /home/my test/home/fol_a/fol_XYZ/My Folder/* and /home/my test/home/fol_a/fol_ABC/My Folder/*

1. Rebuild directory structure and copy appropriate folders and their contents

Running from the parent folder of the tree branch where folders of the same name are located (in our example it would be fol_a , but in your example it would be /Media ) , you can do the following:

NOTE: export these variables , as DEST and SOURCE will be necessary for feeding variables into bash -c of find

DEST=target path SOURCE=name of folder to copy, with its full path recreated BRANCH=the common branch of the same-named folders you wish to copy

export DEST="/home/my test"
export SOURCE="My Folder"
export BRANCH="/home/fol_a"
find "$BRANCH" -type d -name "$SOURCE" -exec bash -c 'mkdir -p "$DEST""$(realpath "{}")" ; cp -r "{}"/* "$DEST""$(realpath "{}")"' \;

NOTE: If you get a message like cp: cannot stat './[FOLDERNAME]/*': No such file or directory **it is not an error, it just means that ** cp -r [FOLDERNAME]/* command happened to execute on a folder that was empty


  • Check the recreated folder tree and contents in your destination folder

To quickly check the folder structure and the files to see if the copying went correctly you can run

tree "$DEST"/..

At this stage(before removing) your overall folder tree will look like so:

home/
├── fol_a
│   ├── fol_ABC
│   │   └── My Folder
│   │       └── file 2
│   └── fol_XYZ
│       └── My Folder
│           ├── file1
│           └── fol_extra
│               └── file 3
└── my test
    └── home
        └── fol_a
            ├── fol_ABC
            │   └── My Folder
            │       └── file 2
            └── fol_XYZ
                └── My Folder
                    ├── file1
                    └── fol_extra
                        └── file 3

14 directories, 6 files


2. Remove the folder tree from the old common branch

Finally (and after double checking all the files are actually within appropriate folders etc.) if everything looks correct , and you are looking to truly move fol_d and its contents (and not just copy) you can finish it off with the following

From the same previously declared common branch (in the above example it was /home/fol_A)

find "$BRANCH" -type d -name "$SOURCE" -exec rm -r "{}" \;

NOTE: You might get messages like find [$SOURCE] :No such file or directory but this will be more or less normal when deleting contents and directory using find and -exec directive.

One last check is to run tree and the final output becomes:

home/
├── fol_a
│   ├── fol_ABC
│   └── fol_XYZ
└── my test
    └── home
        └── fol_a
            ├── fol_ABC
            │   └── My Folder
            │       └── file 2
            └── fol_XYZ
                └── My Folder
                    ├── file1
                    └── fol_extra
                        └── file 3

11 directories, 3 files
11
  • If I'm understanding this correctly, this just handles for one specific fol_d? (i.e. you said "Starting from parent folder of fol_d"). I'm looking to do this for "each instance of folders of that name." i.e. there may be 50 or 100 folders named "fol_d," and all of them should be moved to outside of the source tree.
    – Metal450
    Oct 1, 2020 at 4:51
  • Sorry didn't notice that last part, updating my answer accordingly right away
    – Neticegear
    Oct 1, 2020 at 4:54
  • Still says "Starting from parent folder of fol_d (folder fol_c in the example)" tho - should it now be "starting from any descendant folder of fol_d"? Since again, if it's just the direct parent of that one folder, it wouldn't capture all the other fol_d's on the same level.
    – Metal450
    Oct 1, 2020 at 5:16
  • Yes, anywhere from upper common branch will work, in your example it would be /Media folder
    – Neticegear
    Oct 1, 2020 at 6:14
  • 1
    Yup, I did all 3 commands, including specifying a DEST that I pre-created. Could it have something to do with spaces appearing in paths? Neither SOURCE or DEST have spaces, but some of the photo folders do.
    – Metal450
    Oct 2, 2020 at 6:18

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.