cp file nascosti con motivi glob


13

Situazione:

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

Ho una directory piena di cartelle e file nascosti. Cosa sta succedendo e qual è la soluzione?


dotglobviene tradotto globdotsda zsh che non è un nome opzione valido per bash .

Risposte:


19

Dichiarazione di non responsabilità: questa risposta riguarda specificamente Bash, ma in gran parte si applica alla domanda relativa ai modelli di glob!

Il carattere asterisco ( *) è un carattere jolly. Ci sono un certo set di caratteri che prenderà il posto e il primo carattere che è un punto ( .) non è uno di questi. Questo è un caso speciale proprio a causa del funzionamento dei filesystem Unix, i file che iniziano con un punto sono considerati "nascosti". Ciò significa che strumenti come cp, lsecc., Non li "vedranno" a meno che non venga esplicitamente detto di farlo.

Esempi

Innanzitutto creiamo alcuni dati di esempio.

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

Quindi ora abbiamo il seguente:

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

Ora giochiamo ad alcuni giochi. È possibile utilizzare il comando echoper elencare quale sarebbe un determinato carattere jolly ( *) per un determinato comando in questo modo:

$ 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

Cambiare il comportamento?

È possibile utilizzare il comando shopt -s dotglobper modificare il comportamento di in *modo che oltre ai file simili regfile1corrisponda anche .dotfile1.

estratto dalla bashpagina man

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

Esempio:

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

È possibile ripristinare questo comportamento con questo comando:

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

La tua situazione?

Per te stai dicendo cpche vuoi copiare tutti i file che corrispondono allo schema *e che non ci sono file.

$ cp foo/.* .

Oppure puoi farlo se vuoi tutto nella foocartella:

$ cp foo .

Oppure puoi essere esplicito:

$ cp foot/.* foo/* .

Una forma più compatta che utilizza l'espansione del controvento in bash:

$ cp foo/{.,}* .

In qualsiasi momento puoi usare il echotrucco per vedere quali sono i tuoi schemi di file proposti (questo è il termine elegante per cui fa parte la stella).

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

Per inciso, se hai intenzione di copiare una directory di file + altre directory, in genere vuoi farlo in modo ricorsivo, questo è il -Rpassaggio a cp:

$ cp -R foo/. .

1
Potresti menzionare l'uso di shopt -s dotglob, echo *quindi dare:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Drav Sloan

@DravSloan - grazie per il suggerimento. Aggiunto.
slm

cp -r foo .in genere non funzionerà poiché cpsi rifiuterà di copiare foosu se stesso, probabilmente intendevi cp -R foo/. .. (nota che cp -Rè quello standard).
Stéphane Chazelas,

1
Si noti inoltre che (abbastanza sensatamente), zshnon include .e ..nell'espansione di .*. In zsh, se uno schema non corrisponde, il comando viene interrotto (di nuovo in modo abbastanza sensato), quindi nel caso generale, cp foo/{,.}* .fallirà se non ci sono file nascosti o non nascosti.
Stéphane Chazelas,

7
Questa risposta si applica solo a bash. Il richiedente sta usando zsh, dove la risposta è molto più semplice e shoptnon esiste.
Gilles 'SO- smetti di essere malvagio' il

29

Con zsh, il modo tipico è usare il D qualificatore glob (per includere i file [D] ot):

cp foo/*(D) .

Nota che con o senza D, i globs di zsh non includono ...(come ti aspetteresti).


4

La shell tratta questi file come nascosti quando risolve il *carattere, quindi cpnon riceve nessuno di questi nomi di file come argomenti.

Puoi copiarli specificando esplicitamente cp foo/.* .


1

Se quello che vuoi fare è copiare tutti i file e le directory da una posizione all'altra, puoi usare il rsynccomando standard . Nell'esempio riportato sopra:

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

copierà ricorsivamente tutto il contenuto di foo, inclusi file nascosti e directory nascoste, nella directory corrente. La barra finale alla fine di foo/è importante per rsincronizzare; con esso foovengono copiati solo i contenuti di , senza che anche rsync copierà foo. Per esempio:-

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' 

Ci sono molte altre opzioni disponibili per modificare rsync, inclusa la copia tra macchine.


1

La risposta zsh di Stéphane Chazelas è corretta per una singola espressione con un glob all'interno. Tuttavia, se si desidera impostarlo per tutte le espressioni per impostazione predefinita, è possibile utilizzare

setopt GLOB_DOTS

Mettilo nel tuo ~/.zshrcper renderlo permanente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.