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

9
  • 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, 2023 at 8: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, 2023 at 8:42
  • yes that's right, exclude files from all levels but exclude subfolders in the 1, 2,3,4
    – anmac1789
    Nov 22, 2023 at 9: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 Nov 22, 2023 at 10:09
  • Tar can also do what you want.
    – Bib
    Nov 22, 2023 at 10:27

1 Answer 1

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
7
  • 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, 2023 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, 2023 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, 2023 at 21:43
  • @anmac1789 no other option for cp no. It really doesn't have many options, see man cp.
    – terdon
    Nov 24, 2023 at 8:35
  • can cp "filter" out files and leave only directories kind of like type d that find command does ?
    – anmac1789
    Nov 24, 2023 at 8:40

You must log in to answer this question.

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