10

I am having a the following directory structure:

                Main_Dir
                   |
  -----------------------------------
  Subdir1       Subdir2       Subdir3
     |             |             |
 ---------     ---------     ---------
 |   |   |     |   |   |     |   |   |            
fo1 fo2 f03   fo1 fo2 f03   fo1 fo2 f03

I want to copy all the subdirectories (Subdir1, Subdir2, Subdir3) to a new folder. But I only want to copy fo1 and fo2 folders in the new place.

Not sure how could it be done.

1
  • Copy everything, delete fo3? Commented Nov 8, 2013 at 2:44

4 Answers 4

6

If the tree of directories is more than just ..../f03 you can use this rsync command to copy every fo1 & fo2 and exclude every other directory with the name fo*.

$ rsync -avz --include='fo[12]/' --exclude='fo*/' \
      Main_Dir/ new_Main_Dir/.

When dealing with these types of copy scenarios I always make use of rsync and it's --dry-run & --verbose switches so I can see what it's going to do without actually having to copy the files.

$ rsync -avz --dry-run --verbose --include='fo[12]/' --exclude='fo*/' \
      Main_Dir/ new_Main_Dir/.

Example

Dry run.

$ rsync -avz --dry-run --include='fo[12]/' --exclude='fo*/' \
      Main_Dir/ new_Main_Dir/.
sending incremental file list
./

Subdir1/
Subdir1/fo1/
Subdir1/fo2/
Subdir2/
Subdir2/fo1/
Subdir2/fo2/
Subdir3/
Subdir3/fo1/
Subdir3/fo2/

sent 201 bytes  received 51 bytes  504.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

If you want to see some of rsync's internal logic as to what is being included/excluded then make use of the --verbose switch.

$ rsync -avz --dry-run --verbose --include='fo[12]/' --exclude='fo*/' \
      Main_Dir/ new_Main_Dir/.

sending incremental file list
[sender] showing directory Subdir1/fo2 because of pattern fo[12]/
[sender] showing directory Subdir1/fo1 because of pattern fo[12]/
[sender] hiding directory Subdir1/fo3 because of pattern fo*/
[sender] showing directory Subdir2/fo2 because of pattern fo[12]/
[sender] showing directory Subdir2/fo1 because of pattern fo[12]/
[sender] hiding directory Subdir2/fo3 because of pattern fo*/
[sender] showing directory Subdir3/fo2 because of pattern fo[12]/
[sender] showing directory Subdir3/fo1 because of pattern fo[12]/
[sender] hiding directory Subdir3/fo3 because of pattern fo*/
delta-transmission disabled for local transfer or --whole-file
./
Subdir1/
Subdir1/fo1/
Subdir1/fo2/
Subdir2/
Subdir2/fo1/
Subdir2/fo2/
Subdir3/
Subdir3/fo1/
Subdir3/fo2/
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 201 bytes  received 51 bytes  504.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

If you need to exclude other forms of directories you can add multiple excludes.

4

Use rsync:

rsync -av --exclude="f03" /path/to/Main_Dir/ /pth/to/destination
2

You could try something like this:

find Main_Dir -maxdepth 1 -mindepth 1 -type d | while IFS= read -r subdir; do
   mkdir -p new_dir/"$(basename $subdir)" && 
   cp -r "$subdir"/{fo1,fo2} new_dir/"$(basename $subdir)"/; 
done

The find command returns all direct subdirectories of Main_Dir. basename will return the name of the subdirectory found (e.g. basename Main_Dir/Subdir1 returns Subdir1). You then use the shell's brace expansion to avoid typing fo1 and fo2 multiple times and copy them to the newly created new_dir/$(basename $subdir) directory.

In the specific case you mention where there are only directories under Main_Dir and where there are no spaces or weird characters in the names, you could simplify the above to

cd Main_Dir; for subdir in *; do 
  mkdir -p ../new_dir/$subdir && cp -rv $subdir/{fo1,fo2} ../new_dir/$subdir; 
done
2

If your directory structure is exactly as in your example (i.e. all the fo files are on the same level):

mkdir -p New_Dir/{Subdir1,Subdir2,Subdir3}
for subdir in Subdir1 Subdir2 Subdir3;do
    cp -r Main_Dir/"$dir"/{fo1,fo2} New_Dir/"$dir"/
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .