cp versteckte dateien mit glob mustern

13

Situation :

$ mkdir foo && touch foo/.test
$ cp foo/* .
zsh: no matches found: foo/*
(or bash : cp: cannot stat foo/*’: No such file or directory)

Ich habe ein Verzeichnis voller versteckter Ordner und Dateien. Was passiert und was ist die Lösung?

Gradient
quelle
dotglobwird globdotsvon zsh übersetzt, was ein ungültiger Optionsname für bash ist .

Antworten:

19

Haftungsausschluss: Diese Antwort befasst sich speziell mit Bash, aber ein Großteil davon bezieht sich auf die Frage nach Glob-Mustern!

Das Sternchen ( *) ist ein Platzhalter. Es gibt eine Reihe von Zeichen, die an die Stelle von treten, und das erste Zeichen, das ein Punkt ( .) ist, gehört nicht dazu. Dies ist nur aufgrund der Funktionsweise der Unix-Dateisysteme ein Sonderfall. Dateien, die mit einem Punkt beginnen, gelten als "versteckt". Das bedeutet , dass Werkzeuge wie cp, lsetc. werden nicht „sehen“ , sofern nicht ausdrücklich so zu tun , erzählt.

Beispiele

Lassen Sie uns zunächst einige Beispieldaten erstellen.

$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}

Nun haben wir also folgendes:

$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3

Lass uns jetzt ein paar Spiele spielen. Mit dem Befehl können Sie echoherausfinden, wie ein bestimmtes Platzhalterzeichen ( *) für einen bestimmten Befehl aussehen würde:

$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3


$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2

$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .dotdir*
.dotdir1 .dotdir2

Verhalten ändern?

Sie können den Befehl verwenden shopt -s dotglob, um das Verhalten der zu ändern, *so dass neben Dateien wie regfile1es auch übereinstimmt .dotfile1.

Auszug aus der bashManpage

dotglob If set, bash includes filenames beginning with a `.' in the results 
        of pathname expansion.

Beispiel:

$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

Sie können dieses Verhalten mit diesem Befehl rückgängig machen:

$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3

Deine Situation?

Für Sie sagen Sie, cpdass Sie alle Dateien kopieren möchten, die dem Muster entsprechen *, und dass keine Dateien vorhanden sind.

$ cp foo/.* .

Oder Sie können dies tun, wenn Sie alles im fooOrdner haben möchten :

$ cp foo .

Oder Sie können explizit sein:

$ cp foot/.* foo/* .

Eine kompaktere Form mit Klammererweiterung in bash:

$ cp foo/{.,}* .

Sie können den echoTrick jederzeit verwenden, um die von Ihnen vorgeschlagenen Dateimuster zu ermitteln (dies ist der ausgefallene Begriff für das, woraus der Stern besteht).

$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3

Übrigens, wenn Sie ein Verzeichnis mit Dateien und anderen Verzeichnissen kopieren, möchten Sie dies normalerweise rekursiv tun. Das ist der -RWechsel zu cp:

$ cp -R foo/. .
slm
quelle
1
Vielleicht möchten Sie die Verwendung von erwähnen shopt -s dotglob, echo *dann gibt:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Drav Sloan
@ DravSloan - danke für den Vorschlag. Fügte es hinzu.
slm
cp -r foo .wird in der Regel nicht funktionieren, da cpsich weigern, fooüber sich selbst zu kopieren , meinten Sie wahrscheinlich cp -R foo/. .. (Beachten Sie, dass dies cp -Rder Standard ist).
Stéphane Chazelas
1
Beachten Sie auch, dass (ganz vernünftigerweise) zshnicht .und ..in der Erweiterung von .*. In zsh, wenn ein Muster nicht übereinstimmt, wird der Befehl abgebrochen wird (ganz vernünftig wieder), so im allgemeinen Fall, cp foo/{,.}* .wird scheitern , wenn es keine versteckten ist oder keine nicht-versteckten Dateien.
Stéphane Chazelas
7
Diese Antwort gilt nur für Bash. Der Fragesteller verwendet zsh, wobei die Antwort viel einfacher ist und shoptnicht existiert.
Gilles 'SO- hör auf böse zu sein'
29

Mit zshwird D normalerweise das Glob-Qualifikationsmerkmal verwendet (um [D] ot-Dateien einzuschließen):

cp foo/*(D) .

Beachten Sie, dass Dzsh-Globs .weder mit noch ohne enthalten ..(wie zu erwarten).

Stéphane Chazelas
quelle
4

Die Shell behandelt diese Dateien als versteckt, wenn sie das *Zeichen auflöst. Sie cperhält daher keinen dieser Dateinamen als Argumente.

Sie können sie durch explizite Angabe kopieren cp foo/.* .

Wiederholung
quelle
1

Wenn Sie alle Dateien und Verzeichnisse von einem Ort an einen anderen kopieren möchten, können Sie den Standardbefehl verwenden rsync. Im obigen Beispiel geben Sie Folgendes an:

mkdir foo && touch foo/.test
rsync -a foo/ .

kopiert rekursiv den gesamten Inhalt von foo, einschließlich versteckter Dateien und Verzeichnisse, in das aktuelle Verzeichnis. Der abschließende Schrägstrich am Ende von foo/ist für rsync wichtig. damit werden nur die inhalte von fookopiert, ohne dass es rsync kopiert foo. Beispielsweise:-

mkdir src && mkdir dest && touch src/.test
rsync -a src  dest    // copies 'src' contents to 'dest/src'
rsync -a src/ dest    // copies 'src' contents to 'dest' 

Es gibt viele andere Optionen zur Optimierung von Rsync, einschließlich des Kopierens zwischen Computern.

Rob Swarbrick
quelle
1

Die zsh- Antwort von Stéphane Chazelas ist für einen einzelnen Ausdruck mit einem Globus richtig. Wenn Sie es jedoch standardmäßig für alle Ausdrücke festlegen möchten, können Sie verwenden

setopt GLOB_DOTS

Legen Sie es in Ihr ~/.zshrc, um es dauerhaft zu machen.

Sparhawk
quelle