Open therealchfkch opened 2 weeks ago
Nushell issue (just in case) https://github.com/nushell/nushell/issues/13717
This is specified by POSIX. Quoting from https://pubs.opengroup.org/onlinepubs/9799919799/utilities/cp.html (emphasis mine):
If target exists and names an existing directory, the name of the corresponding destination path for each file in the file hierarchy shall be the concatenation of target, a single
<slash>
character if target did not end in a<slash>
, and the pathname of the file relative to the directory containing source_file.If target does not exist and two operands are specified, the name of the corresponding destination path for source_file shall be target; the name of the corresponding destination path for all other files in the file hierarchy shall be the concatenation of target, a
character, and the pathname of the file relative to source_file.
Ah okay. But i do not fully understand how to achieve the result of step 2 if the directory already exiats.
Also (a bit offtopic), i used the "old" coreutils (i guess GNU), and there it behaves like step 2 even if the target exists. Is their cp not POSIX compliant?
Sorry i am not very experienced in this.
Also (a bit offtopic), i used the "old" coreutils (i guess GNU), and there it behaves like step 2 even if the target exists. Is their cp not POSIX compliant?
Are you sure? What version of cp
are you using? Here's what I see:
tavianator@graphene $ mkdir source-dir target-dir
tavianator@graphene $ touch source-dir/file-1 source-dir/file-2
tavianator@graphene $ cp -r source-dir target-dir
tavianator@graphene $ tree target-dir
target-dir
└── source-dir
├── file-1
└── file-2
2 directories, 2 files
tavianator@graphene $ cp --version
cp (GNU coreutils) 9.5
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Torbjörn Granlund, David MacKenzie, and Jim Meyering.
By the way this issue title ("target_dir is empty") and description ("target-dir
does not exist yet") don't match.
Ok so i have made a mistake and mixed something up. First of all, you are right, the descritption of the topic is slightly off, i am editing it.
The major mistake i made was that i mixed up my parameters.
The correct version i tried (and succeded in GNU coreutils 9.5) was cp -r source-dir/. target-dir
which then always copies only the content of source-dir to target-dir, not the directory source-dir itself.
How can i reach this with uutils/coreutils? Should they not be parameter-compatible? I could not find anything with cp --help, because i think it is again rather something POSIX-specific? Again, i am quite new to the technical side of this.
┌── ~
└─▶ ❯mkdir source-dir
┌── ~
└─▶ ❯ touch source-dir/file1.md source-dir/file2.md
┌── ~
└─▶ ❯ cp -r source-dir/. target-dir
┌── ~
└─▶ ❯ erd target-dir/
0 B ┌─ file1.md
0 B ├─ file2.md
target-dir
2 files
┌── ~
└─▶ ❯ cp -r source-dir/. target-dir
┌── ~
└─▶ ❯ erd target-dir/
0 B ┌─ file1.md
0 B │ ┌─ file1.md
0 B │ ├─ file2.md
├─ source-dir
0 B ├─ file2.md
target-dir
1 directory, 4 files
┌── ~
└─▶ ❯ rm -r target-dir/source-dir
┌── ~
└─▶ ❯ erd target-dir/
0 B ┌─ file1.md
0 B ├─ file2.md
target-dir
2 files
// The above part is in nushell (uutils), below is bash with GNU coreutils.
┌── ~
└─▶ ❯ bash
$ cp -r source-dir/. target-dir
$ erd target-dir/
0 B ┌─ file1.md
0 B ├─ file2.md
target-dir
2 files
Ah, with source-dir/.
, the GNU behaviour is right and uutils is wrong.
Describe the bug
When i use
cp -r source-dir target-dir
andtarget-dir
does not exist yet, it copies the content (without thesource-dir
folder) totarget-dir
. On the other hand, whentarget-dir
already exists, the result istarget-dir/source-dir
with the contents.I am not sure which of the 2 expected behaviors are intended or how to avoid it.
How to reproduce
source-dir
for this test) and place one or more dummy files in it (file1.md
,file2.md
).cp -r source-dir target-dir
target-dir
cp -r source-dir target-dir
againtarget-dir
namedsource-dir
Expected behavior
step 4 produces results like in step 2 & 3 as described above
OR
step 2 produces results like step 4 & 5 as described above
Additional Information
output after step 2:
erd target-dir/
0 B ┌─ file1.md 0 B ├─ file2.md target-dir
2 files
output after step 4:
erd target-dir/
0 B ┌─ file1.md 0 B ├─ file2.md ┌─ source-dir 0 B ├─ file1.md 0 B ├─ file2.md target-dir
1 directory, 4 files
Run with --debug and -v flag
output of step 2
cp -r source-dir target-dir --debug -v
'/home/roman/source-dir' -> '/home/roman/target-dir/' '/home/roman/source-dir/file1.md' -> '/home/roman/target-dir/file1.md' copy offload: unknown, reflink: unsupported, sparse detection: no '/home/roman/source-dir/file2.md' -> '/home/roman/target-dir/file2.md' copy offload: unknown, reflink: unsupported, sparse detection: no
output of step 4
cp -r source-dir target-dir --debug -v
'/home/roman/source-dir' -> '/home/roman/target-dir/source-dir' '/home/roman/source-dir/file1.md' -> '/home/roman/target-dir/source-dir/file1.md' copy offload: unknown, reflink: unsupported, sparse detection: no '/home/roman/source-dir/file2.md' -> '/home/roman/target-dir/source-dir/file2.md' copy offload: unknown, reflink: unsupported, sparse detection: no
Notes
I have also opened an issue at nushell, but i think this is an upstream issue, so i opened this one after some discussion.