Seltsames Verhalten in rekursiver Kopie

7

Könnte jemand erklären, warum dies passiert?

Ganz konkret: Warum wird der Inhalt einer 1 nach f kopiert? Und warum wird f nach g kopiert?

$ tree  
.

0 directories, 0 files

$ mkdir 1
$ mkdir 2
$ touch 1/a
$ touch 1/b
$ mkdir 1/c
$ touch 1/c/x
$ tree
.
├── 1
│   ├── a
│   ├── b
│   └── c
│       └── x
└── 2

3 directories, 3 files

$ cp -r 1/* 2/*
zsh: no matches found: 2/*

$ cp -r 1/* 2/*
$ mkdir 2/f
$ mkdir 2/g
$ cp -r 1/* 2/*
$ tree
.
├── 1
│   ├── a
│   ├── b
│   └── c
│       └── x
└── 2
    ├── f
    └── g
        ├── a
        ├── b
        ├── c
        │   └── x
        └── f

7 directories, 6 files
MPV
quelle
Ich denke, Sie haben ein Extra cp -r 1/* 2/*drin - es wird zweimal hintereinander mit (anscheinend) unterschiedlichen Ergebnissen durchgeführt. Es sollte sich immer darüber beschweren, dass es keinen findet, 2/*weil die Shell diesen Glob nicht erweitern kann - nichts passt dazu. Und der Inhalt von 1wird fin diesem Beispiel nicht kopiert .
Shawn J. Goff
2
Wenn das Ziel von nicht cpeindeutig ist, können Sie es versuchen --target-directory, z. B. cp --target-directory=2 fileglob1 fileglob2finde ich diese Option sehr nützlich in Skripten, in denen ich nicht sicher bin, welche Globs funktionieren und welche nicht. Es hilft, versehentliches Überschreiben zu verhindern. (Einige Versionen cperlauben -t.)
Aaron D. Marasco

Antworten:

8

Für cpist das Ziel das letzte Argument auf der Kommandozeile. Sie haben 2/gals letztes Argument angegeben.

Bevor cpausgeführt wird, werden die Befehlsparameter erweitert. 1/*erweitert sich auf 1/a 1/b 1/c. 2/*erweitert sich auf 2/f 2/g. Der letzte ausgeführte Befehl ist cp -r 1/a 1/b 1/c 2/f 2/g, der alle Argumente (außer dem letzten) nach kopiert 2/g.

Wenn Sie beabsichtigen, Dinge zu kopieren, 2ist der zweite Glob nicht erforderlich, um den Befehl auszuführen cp -r 1/* 2/. Wenn Sie beabsichtigen, Dinge an mehrere Ziele zu kopieren, können Sie dies nicht mit just angeben cp. Sie können eine kleine Schleife wie die folgende verwenden:

#!/bin/sh
for path in ./2/*/; do
  cp -r 1/* "$path"
done
Shawn J. Goff
quelle