1

This is a follow-up question to my original post: find & cp command doesn't copy 1st level directory

I have a directory structure like this:

test folders
├── 1
│   ├── 1-1
│   ├── 1-2
│   └── 1-3
├── 2
│   ├── 2-1
│   ├── 2-2
│   └── 2-3
├── 3
│   ├── 3-1
│   ├── 3-2
│   └── 3-3
└── 4
    ├── 4-1
    ├── 4-2
    └── 4-3

16 directories, 0 files

and I am struggling with copying ONLY the 1st level folders -- 1,2,3,4 excluding all subfolders using find & cp commands

├── 1
├── 2
├── 3
└── 4

Working directory is /home/username/Downloads/test folders.

My failed attempt is in the linked question. There we've established the fact that cp doesn't see find's commands with -maxdepth.

Is there another command with find and cp that allows -maxdepth to make it easier to copy files? Is there even a -maxdepth equivalent for cp, if find's commands can't be linked with cp?

[edit]: In addition, I want to only copy the 1st level directories, such as 1, 2, 3 and 4. I do not want to copy files. Sorry for the confusion

  • 1
    Does it have to be cp? rsync usually handles those kind of sophisticated copy requirements much better. See rsync recursively with a certain depth of subfolders for example. – aviro Nov 22 '23 at 08:40
  • 2
    By the way, I assume you want to copy the 1st level directories including the files in them, just without the subfolders, is that right? – aviro Nov 22 '23 at 08:42
  • yes that's right, exclude files from all levels but exclude subfolders in the 1, 2,3,4 – anmac1789 Nov 22 '23 at 09:44
  • 1
    Anmac1789 your response ^^ reads to me as "yes" agreeing to the first level directories being copied with their files, but then you say "exclude files from all levels". Please edit your question to state whether copying should include first level directories and their immediate files, or copying should include the first level directories only, without any files – Chris Davies Nov 22 '23 at 10:09
  • Tar can also do what you want. – Bib Nov 22 '23 at 10:27
  • Looks like you are using GNU tools. If you don't mind the warning messages because your didn't mention the -r option, why not use cp --parents */* destination_directory? – xhienne Nov 22 '23 at 10:42
  • @xhienne Does --parents only copy the level that you define ? – anmac1789 Nov 22 '23 at 20:51
  • @anmac1789 No, cp --parents */* dest will copy the files among your parameters */* (if you want to copy more levels, then change the parameter: */*/*, */*/*/*, etc). The --parents option will just recreate the directory hierarchy for those files in the destination directory. Just try it out! – xhienne Nov 22 '23 at 21:43
  • This works as intended by copying folders which are 3 levels deep but it copies all 3 levels. How do I copy, just the 3rd level ? – anmac1789 Nov 22 '23 at 22:09

1 Answers1

0

If you only want to copy the directories and no files or sub-directories, it' easy:

terdon@oregano test folders $ tree
.
├── 1
│   ├── 1-1
│   ├── 1-2
│   ├── 1-3
│   ├── file-1
│   └── file-2
├── 2
│   ├── 2-1
│   ├── 2-2
│   ├── 2-3
│   ├── file-1
│   └── file-2
├── 3
│   ├── 3-1
│   ├── 3-2
│   ├── 3-3
│   ├── file-1
│   └── file-2
└── 4
    ├── 4-1
    ├── 4-2
    ├── 4-3
    ├── file-1
    └── file-2

17 directories, 8 files

Using the above example, you can re-create the top level directories with:

terdon@oregano test folders $ find . -maxdepth 1 -type d -exec mkdir ../results/{} \;
mkdir: cannot create directory ‘../results/.’: File exists
$ tree ../results/
../results/
├── 1
├── 2
├── 3
└── 4

5 directories, 0 files

You can safely ignore the error message. That is just because it also finds ., the current directory, and tries to create ../results/., that current directory, which already exists.

If you also want to copy the top-level files, you can do it in two steps:

terdon@oregano test folders $ find . -maxdepth 1 -type d -exec mkdir ../results/{} \;
mkdir: cannot create directory ‘../results/.’: File exists
$ find . -maxdepth 2 -type f -exec cp {} ../results/{} \;

Which produces:

$ tree ../results/
../results/
├── 1
│   ├── file-1
│   └── file-2
├── 2
│   ├── file-1
│   └── file-2
├── 3
│   ├── file-1
│   └── file-2
└── 4
    ├── file-1
    └── file-2

You can also do it in a single pass with:

$ find . -maxdepth 1 -type d -exec sh -c 'mkdir ../results/$1 && cp {}/* ../results/$1' sh {} \;
mkdir: cannot create directory ‘../results/.’: File exists
cp: -r not specified; omitting directory './3/3-1'
cp: -r not specified; omitting directory './3/3-2'
cp: -r not specified; omitting directory './3/3-3'
cp: -r not specified; omitting directory './1/1-1'
cp: -r not specified; omitting directory './1/1-2'
cp: -r not specified; omitting directory './1/1-3'
cp: -r not specified; omitting directory './4/4-1'
cp: -r not specified; omitting directory './4/4-2'
cp: -r not specified; omitting directory './4/4-3'
cp: -r not specified; omitting directory './2/2-1'
cp: -r not specified; omitting directory './2/2-2'
cp: -r not specified; omitting directory './2/2-3'

Since we are using cp without -r, only files will be copied. You'll get those warnings, but again, you can safely ignore them. You can also silence them by redirecting to /dev/null:

find . -maxdepth 1 -type d -exec sh -c 'mkdir ../results/$1 && cp {}/* ../results/$1' sh {} \; 2>/dev/null
terdon
  • 242,166
  • so does it mean that cp without -r only copies files in the current directory and with -r it's suppose to copy subdirectories as well but cp..doesn't have a switch for copying subdirectories at a certain depth level ? – anmac1789 Nov 22 '23 at 20:54
  • @anmac1789 -r doesn't differentiate between files and directories. Remember, on *nix systems like Linux, everything is a file. So cp alone, without -r can only copy files, but if you give it -r it means "copy everything, including directories". So yes, it has no understanding of depth, it's either just a file, or everything. – terdon Nov 22 '23 at 21:12
  • ok gotcha makes sense so there is no really other option for cp that excludes depth except using mkdir with {} ? – anmac1789 Nov 22 '23 at 21:43
  • @anmac1789 no other option for cp no. It really doesn't have many options, see man cp. – terdon Nov 24 '23 at 08:35
  • can cp "filter" out files and leave only directories kind of like type d that find command does ? – anmac1789 Nov 24 '23 at 08:40
  • @anmac1789 no, it doesn't. Didn't you read man cp as I suggested? – terdon Nov 24 '23 at 09:07
  • ok, ur right cp doesn't have many flexible commands – anmac1789 Nov 24 '23 at 09:19