1

I'm trying to copy a single file to all of the deepest subdirectories in a tree structure. Imagine it looks like this:

bar
dir1
 |  |
 |  +--dir2
 |    |
 |    +--dir3
 |  +--dir4
 |    |
 |    +--dir5
 |  +--dir6
 |    |
 |    +--dir7

I want "bar" to be copied only to the deepest subdirectories, like this:

bar
dir1
 | +--dir2
 |   |
 |    +--dir3
 |     | 
 |     +-- bar
 | +--dir4
 |   |
 |   +--dir5
 |     | 
 |     +-- bar
 | +--dir6
 |   |
 |   +--dir7
 |     | 
 |     +-- bar

I'm not sure how to approach this, since files end up in middle directories sometimes, but I can't find a way to target the deepest subdirectories.

Edit: my attempt at solving this. This copies to all directories inconsistently, still for some reason, not just the deepest ones.

find . -exec cp -r bar {} \; -type d -links 2
7
  • 2
    Please add your attempt, even if failed. Have a look at <stackoverflow.com/a/27629943>, you will be able to easily answer your own question with that and the -exec option of find :)
    – Quasímodo
    Jul 21, 2020 at 13:19
  • Added, thanks that link helped.
    – bactro
    Jul 21, 2020 at 13:52
  • @bactro check the command you typed in the question, seems wrong.
    – Prvt_Yadav
    Jul 21, 2020 at 14:05
  • 1
    Do you really need a distinct copy of the original file in each directory? Would hard-linking to the reference copy be better? Jul 21, 2020 at 17:44
  • 1
    It depends on whether you want an identical file in each directory (maybe a standard config or script), or whether it gets modified differently in each directory (maybe stores usage stats). If it is a standard file that might need updating, then you would need to update all of them. However ... a file consists of a directory entry (just name and a "number"), and a disc area called an inode which is identified by the number and holds all the data blocks, permissions, timestamps etc. Linux allows "hard links" which lets many dir entries point to the same inode. So only one copy of the data. Jul 21, 2020 at 22:13

2 Answers 2

1

Solution: On the directory containing bar,

find . -type d -links 2 -exec cp bar {} \;

Your original attempt

find . -exec cp -r bar {} \; -type d -links 2

contains no syntactic errors, but does not behave as you expected. Because -exec comes before the -type and -links filters, the filters never apply and exec gets everything under (and including) the current directory, not only regular files but also directories. If you are not convinced, check the output of

find . -exec echo X{}X \; -type d -links 2 -exec echo Y{}Y \;

You will see that all the files get listed between two X, but only only the correct dir{3,5,7} files between two Y. That explains why bar popped up in middle directories too.

Also, the -r option activates recursive copies. Since what is being copied is a regular file (bar), -r is not needed.

0

You can use:

find . -type d -links 2 -exec cp  file  {} \;

It will find directories having 2 hard links, and then copy your file to that particular directory.

You must log in to answer this question.

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