Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to the Power Users community on Codidact!

Power Users is a Q&A site for questions about the usage of computer software and hardware. We are still a small site and would like to grow, so please consider joining our community. We are looking forward to your questions and answers; they are the building blocks of a repository of knowledge we are building together.

Post History

75%
+4 −0
Q&A How to copy files preserving one directory up

Assuming innermost directories are not empty, in any POSIX compliant system, find . -type d -links 2 -exec cp -r {} . \; In a GNU Linux system, a more performant alternative is find . -type d ...

posted 2y ago by Quasímodo‭  ·  edited 2y ago by mcp‭

Answer
#5: Post edited by user avatar mcp‭ · 2022-11-02T12:18:47Z (about 2 years ago)
Remove duplicate 'a'.
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • ### How does it work?
  • #### Leaf directories have only two hard links
  • Every directory in a Linux system is indexed with at least two [hard links][0].
  • A leaf directory, by definition a directory without any sub-directory, has only two hard links, `path/to/dir` and `path/to/dir/.`.
  • On the other hand, a a directory with one sub-directory would have an additional hard link, namely `path/to/dir/subdir/..`.
  • Conclusion: The number _h_ of hard links of a directory is `h=s+2`, being _s_ the number of sub-directories.
  • #### The -exec option
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1 .
  • cp -r d3_sd2 .
  • while the latter will spawn
  • cp -rt . d1_sd1 d3_sd2
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • ### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • ### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [0]: https://en.wikipedia.org/wiki/Hard_link
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • ### How does it work?
  • #### Leaf directories have only two hard links
  • Every directory in a Linux system is indexed with at least two [hard links][0].
  • A leaf directory, by definition a directory without any sub-directory, has only two hard links, `path/to/dir` and `path/to/dir/.`.
  • On the other hand, a directory with one sub-directory would have an additional hard link, namely `path/to/dir/subdir/..`.
  • Conclusion: The number _h_ of hard links of a directory is `h=s+2`, being _s_ the number of sub-directories.
  • #### The -exec option
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1 .
  • cp -r d3_sd2 .
  • while the latter will spawn
  • cp -rt . d1_sd1 d3_sd2
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • ### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • ### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [0]: https://en.wikipedia.org/wiki/Hard_link
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
#4: Post edited by user avatar Quasímodo‭ · 2022-10-30T09:45:20Z (about 2 years ago)
Define leaf directories and clarify.
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • #### How does it work?
  • Counting the number of links is a classical way to distinguish leaf directories, that only have 2 of them (one from its parent, `parent/leaf`, and one in itself, `leaf/.`), of other directories.
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1 .
  • cp -r d3_sd2 .
  • while the latter will spawn
  • cp -rt . d1_sd1 d3_sd2
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • #### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • #### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • ### How does it work?
  • #### Leaf directories have only two hard links
  • Every directory in a Linux system is indexed with at least two [hard links][0].
  • A leaf directory, by definition a directory without any sub-directory, has only two hard links, `path/to/dir` and `path/to/dir/.`.
  • On the other hand, a a directory with one sub-directory would have an additional hard link, namely `path/to/dir/subdir/..`.
  • Conclusion: The number _h_ of hard links of a directory is `h=s+2`, being _s_ the number of sub-directories.
  • #### The -exec option
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1 .
  • cp -r d3_sd2 .
  • while the latter will spawn
  • cp -rt . d1_sd1 d3_sd2
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • ### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • ### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [0]: https://en.wikipedia.org/wiki/Hard_link
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
#3: Post edited by user avatar Quasímodo‭ · 2022-08-04T15:49:54Z (over 2 years ago)
Fix mistake
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • #### How does it work?
  • Counting the number of links is a classical way to distinguish leaf directories, that only have 2 of them (one from its parent, `parent/leaf`, and one in itself, `leaf/.`), of other directories.
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1/f1.txt .
  • cp -r d3_sd2/f1.txt .
  • while the latter will spawn
  • cp -rt . d1_sd1/f1.txt d3_sd2/f1.txt
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • #### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • #### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • #### How does it work?
  • Counting the number of links is a classical way to distinguish leaf directories, that only have 2 of them (one from its parent, `parent/leaf`, and one in itself, `leaf/.`), of other directories.
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1 .
  • cp -r d3_sd2 .
  • while the latter will spawn
  • cp -rt . d1_sd1 d3_sd2
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • #### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • #### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
#2: Post edited by user avatar Quasímodo‭ · 2022-08-04T15:49:12Z (over 2 years ago)
Expanded explanation
  • Assuming innermost directories are not empty,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • #### How does it work?
  • Counting the number of links is a classical way to distinguish leaf directories, that only have 2 of them (one from its parent, `parent/leaf`, and one in itself, `leaf/.`), of other directories.
  • #### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • #### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • Assuming innermost directories are not empty, in any POSIX compliant system,
  • find . -type d -links 2 -exec cp -r {} . \;
  • In a GNU Linux system, a more performant alternative is
  • find . -type d -links 2 -exec cp -rt . {} +
  • since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).
  • #### How does it work?
  • Counting the number of links is a classical way to distinguish leaf directories, that only have 2 of them (one from its parent, `parent/leaf`, and one in itself, `leaf/.`), of other directories.
  • The `-exec` option executes the corresponding command for each found file if `;` terminated or for the maximum number of files if `+` terminated. So, for example, the first will spawn
  • cp -r d1_sd1/f1.txt .
  • cp -r d3_sd2/f1.txt .
  • while the latter will spawn
  • cp -rt . d1_sd1/f1.txt d3_sd2/f1.txt
  • See that the latter is only possible because the `-t` option, available in `cp` from GNU coreutils, allows the target to be specified before the files to be copied. ([`-exec cp -r {} . +` is not valid!][1])
  • #### Before
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • └── d3/
  • └── d3_sd1/
  • └── d3_sd2/
  • └── f1.txt
  • 5 directories, 2 files
  • ```
  • #### After
  • ```
  • $ tree
  • ./
  • ├── d1/
  • │   └── d1_sd1/
  • │   └── f1.txt
  • ├── d1_sd1/
  • │   └── f1.txt
  • ├── d3/
  • │   └── d3_sd1/
  • │   └── d3_sd2/
  • │   └── f1.txt
  • └── d3_sd2/
  • └── f1.txt
  • 7 directories, 4 files
  • ```
  • [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html
#1: Initial revision by user avatar Quasímodo‭ · 2022-08-03T20:40:46Z (over 2 years ago)
Assuming innermost directories are not empty,

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

In a GNU Linux system, a more performant alternative is

    find . -type d -links 2 -exec cp -rt . {} +

since it only spawns an optimal number of `cp` process (a single one if the size of the argument list is not large).

#### How does it work?

Counting the number of links is a classical way to distinguish leaf directories, that only have 2 of them (one from its parent, `parent/leaf`, and one in itself, `leaf/.`), of other directories.

#### Before
```
$ tree
./
├── d1/
│   └── d1_sd1/
│       └── f1.txt
└── d3/
    └── d3_sd1/
        └── d3_sd2/
            └── f1.txt

5 directories, 2 files
```
#### After
```
$ tree
./
├── d1/
│   └── d1_sd1/
│       └── f1.txt
├── d1_sd1/
│   └── f1.txt
├── d3/
│   └── d3_sd1/
│       └── d3_sd2/
│           └── f1.txt
└── d3_sd2/
    └── f1.txt

7 directories, 4 files
```