Wie kopiere ich eine Datei, die mit einem Punkt beginnt?

26

Ich versuche, alle Dateien unter Verzeichnis A in Verzeichnis B zu kopieren. Alle Dateien unter Verzeichnis A beginnen mit Punkt, zum Beispiel:

A/.a
A/.b
A/.c

was ich gefunden habe wenn ich benutze cp A/* B:, bekomme immer fehler:

cp: cannot stat 'A/*': no such file or directory

Es scheint , gibt es keine Option für cpwie lszum Griff Einträge mit Punkt gestartet, hat jemand Ahnung , wie es zu beheben?

user59285
quelle

Antworten:

34

Der Grund ist , weil in bash, *enthält keine Dateien , mit einem Punkt beginnen ( .).

Du kannst rennen

cp A/.* B

Es wird Sie warnen , dass es nicht kopieren .oder .., oder alle Unterverzeichnisse, aber das ist in Ordnung.

Wenn Sie Punktdateien und normale Dateien zusammen kopieren möchten, führen Sie den Befehl aus

cp A/.* A/* B

Du könntest auch rennen

shopt -s dotglob
cp A/* B

das wird funktionieren bash, aber nicht sh.

Und wenn Sie nichts dagegen haben, dass auch Unterverzeichnisse kopiert werden, ist dies die einfachste:

cp -R A/ B

Tipp: Wenn Wildcards jemals nicht das tun, was Sie erwarten, versuchen Sie, sie mit Echo auszuführen, z

$ echo A/*
A/file1 A/file2

$ echo A/.*
A/. A/.. A/.hidden1 A/.hidden2

$ echo A/.* A/*
A/. A/.. A/.hidden1 A/.hidden2 A/file1 A/file2

$ shopt -s dotglob
$ echo A/*
A/file1 A/file2 A/.hidden1 A/.hidden2
Mikel
quelle
Das ist nur ein Problem, wenn Sie verwenden -r. Ohne -rwird es nur die Verzeichnisse überspringen.
Mikel
Und das Beispiel, das ich benutze, -Rsollte auch gut funktionieren. Wenn Sie denken, dass es falsch ist, erklären Sie bitte, warum.
Mikel
7

Wenn Bash, können Sie einstellen, dotglobbevor Sie kopieren

shopt -s dotglob
cp A/* /destination

Oder eine Programmiersprache

$ ruby -rfileutils -e  'Dir[".*"].each {|x| FileUtils.copy(x,"/destination") if File.file?x}'

Wenn Sie dotglob nicht einstellen möchten, nur

cp A/.* /destination 2>/dev/null

quelle
Mit dotglob OP werden auch alle nicht ausgeblendeten Dateien kopiert, was er nicht will.
Peoro
@peoro, du solltest die Frage nochmal lesen. Alle Dateien in Asind ausgeblendet. Er will das nur kopieren.
7

Was Sie suchen, ist mehr im Sinne von:

cp A/.??* B/

Dies entspricht allen Punktedateien, jedoch nicht "." oder "..". Die meisten der oben genannten Lösungen sind in Ordnung, solange Sie nicht rekursiv arbeiten. Aber sobald du etwas machen willst wie:

cp -R A/.??* B/

Ohne das Auslassen von ".." kopieren Sie alles aus dem übergeordneten Verzeichnis nach unten, auch Nicht-Punktedateien.

John Westlund
quelle
1
Dadurch werden Punktdateien, die ein einzelnes Zeichen wie .aoder sind, übersehen .x. Das kürzeste Globbing Muster Ich habe festgestellt , dass Streichhölzer jede Punktdatei mit Ausnahme .und ..ist .[^.]*.
Pavon
2

Ich habe gerade Folgendes ausprobiert und es funktioniert einfach ...

cp A/.* B/
Andrew White
quelle
2
Dies wird auch übergeben A/.und A/..als Parameter an cp, was problematisch sein könnte, falls OP auch Verzeichnisse kopieren muss (mit cp -r)
peoro
2

Das ist nicht cpdie Schuld , es ist bash: bash wird *in allen nicht versteckten (dh nicht mit .) Dateien erweitert.

Bash wird .*( A/.*in Ihrem Fall also) mit allen Dateien erweitert, die mit beginnen ., enthält aber leider auch .und ..(aktuelle und übergeordnete Verzeichnisse), die Sie wahrscheinlich überspringen möchten. (Beachten Sie, dass andere Shells, wie zsh, sie nicht einschließen würden, und IIRC schlägt ebenfalls zu, nachdem einige Optionen festgelegt wurden.)

Eine einfache Lösung könnte darin bestehen, Dateien zu entfernen .und ..aus Dateien zu entfernen .*, die auf (sehr) hackige Weise wie folgt übereinstimmen:

cp $( for F in A/.*; do echo $F | grep -v "^\.*$"; done ) B

oder dieses (wahrscheinlich sauberer: es verwendet find, um die zu kopierenden Dateien zu finden):

cp $( find A -maxdepth 1 -mindepth 1 -name ".*" ) B

Aber Sie werden wahrscheinlich sauberere Lösungen finden.

peoro
quelle
Warum sollten Sie einen for loopzusätzlichen grepProzess erstellen , um einen Job wie diesen zu erledigen cp A/.*? cpignoriert das "." und ".." Verzeichnisse.
1

Wenn alle mit einem Punkt beginnen, verwenden Sie einfach A/.*:

[holt@Michaela test]$ cp A/* B
cp: cannot stat `A/*': No such file or directory

[holt@Michaela test]$ cp A/.* B
cp: omitting directory `A/.'
cp: omitting directory `A/..'
[holt@Michaela test]$ ls -al B
total 8
drwxrwxr-x. 2 holt holt 4096 2011-03-31 16:57 .
drwxrwxr-x. 4 holt holt 4096 2011-03-31 16:57 ..
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .a
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .b
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .c

Hoffe das hilft!

Xavier Holt
quelle
1

Sie können dieses Skript verwenden

IFS = $ '\ n'; für act in $ (finde A -d 1); do cp -R "$ act" B; getan

teki
quelle
0

Kopieren:

cp A/.* B

Liste:

ls -l A/.*

liste dateien ohne absteigende verzeichnisse auf:

ls -ld A/.*
Gesegneter Aussenseiter
quelle
0

Sie müssen ausschließen. und .. aus der Dateiliste an cp übergeben!

Das ist sicher:

ls -1d A/.[a-zA-Z]* | xargs -i cp -rp {} B
AmitP
quelle
0

Dies ist ein alter Thread ... aber ich war immer in der Lage, alle Dateien zu kopieren. Einschließen von Dateien / Ordnern, die mit "." Beginnen

Beispiel kopiert alle Dateien und Ordner:

cp -aup /root/.* / backup / root /

Ontologik
quelle