Come posso ottenere mv (o il carattere jolly *) per spostare i file nascosti?


134

Sto migrando la mia directory home da un vecchio sistema a uno nuovo, e il tarball che ho creato contiene tutto, inclusi file nascosti come .bashrc. Tuttavia, quando sposto il contenuto del tarball decompresso (che si trova in / tmp) nella mia nuova directory home, i file nascosti non vengono copiati ( mv /tmp/home/rcook/* /home/rcook/). Come posso convincere mv a spostarli?

In realtà, penso che il problema non sia con la MV, ma con il colpo di grazia di Bash. Se lo faccio:

mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/

Lo vedo:

a/:
.  ..  .foo

b/:
.  ..  bar

a/.foonon si mosse. Quindi, come posso ottenere il jolly * per trovare i file nascosti?

Sì, suppongo di poter decomprimere il tarball direttamente nella mia directory home, ma il tarball si decomprime in home/rcook/...e voglio essere sicuro di sovrascrivere il nuovo .bashrc, ecc. Con le vecchie versioni personalizzate e sapere come trovare e spostare i file nascosti è un'abilità utile. Suggerimenti?


Alcune risposte suggeriscono di fare qualcosa del genere mv src/.* dest/. Tuttavia, ho provato questo nelle mie directory di test e ho riscontrato errori. Iniziare con:

rcook$ ls -a a/ b/
a/:
.  ..  bar  .foo

b/:
.  ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
.  ..  bar

b/:
.  ..  .foo

Che cosa sto facendo di sbagliato?


Risposte:


147

Puoi farlo :

shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/

Puoi mettere

shopt -s dotglob

nel tuo ~/.bashrcse vuoi che sia il valore predefinito.

Vedi http://mywiki.wooledge.org/glob


Un altro approccio per copiare i file dot:

mv /tmp/home/rcook/.[!.]* /home/rcook/

Non usare il modello ..*come corrisponde ..(puntatore alla directory principale). Se sono presenti file il cui nome inizia con due punti ( ..something), utilizzare anche il modello ..?*.


Controlla le aggiunte che ho inserito in fondo alla mia domanda. Grazie.
Randall Cook,

1
Nulla di sbagliato, .e ..sono dir speciali: rispettivamente dir corrente e dir parent . È solo un avvertimento. Migliore shopt -s dotglobsoluzione d' uso
Gilles Quenot,

Ho finito per fare solo due mosse: mv home/rcook/* /home/rcook/seguito da mv home/rcook/.* /home/rcook/. Questo ha funzionato, anche se vorrei aver seguito il link e letto prima la modalità dotglob. Mi avrebbe risparmiato un passo. +1
Randall Cook,

Quindi il secondo approccio richiede l'uso di percorsi assoluti?
franzlorenzon,

3
Se stai usando zsh, puoi usare il Dqualificatore globbing o l' GLOB_DOTSopzione shell .
mgalgs,

43

Nelle tue aggiunte, hai riscontrato errori ma il codice ha ancora funzionato. L'unica cosa da aggiungere è che hai detto solo di copiare i file punto. Provare:

mv src/* src/.* dst/

Riceverai comunque gli errori per. e .. voci, che va bene. Ma la mossa dovrebbe avere successo.

~/scratch [andrew] $ mv from/* from/.* to/
mv: cannot move from/.’ to to/.’: Device or resource busy
mv: cannot remove from/..’: Is a directory
~/scratch [andrew] $ ls -a from/ to/
from/:
.  ..

to/:
.  ..  test  .test

1
Aspetti positivi, @AndrewSchwartz. Mi piace anche questo approccio. Penso che meriti un maggiore riconoscimento.
Randall Cook,

Mi piace che @Drake Clarris risponda un po 'di più, perché sto eseguendo Amazon AWS CodeBuild e il codice di ritorno diverso da zero ha causato l'arresto della mia build. Alla fine ho spostato l'unico .hiddenfile che avevo esplicitamente per risolvere il mio problema.
HeyWatch, questo

Se il codice di uscita diverso da zero è un problema, è possibile eliminarlo, ad esempio aggiungendo || :( ||significa eseguire quanto segue su falso / errore, :è il comando noop). Ma ciò eliminerebbe anche gli errori legittimi, ad esempio la cartella di destinazione non esiste. Non riesco a trovare un modo più elegante usando mvper escludere le voci .e ... Butt big plus per me su cp non sta scrivendo nuovi file su disco.
Andrew Schwartz,

10

Se ti trovi ls -lin una directory, vedrai .e ..tra i file elencati. Quindi, penso che mv .* /desttenga conto di questi suggerimenti. Provare:

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/

questo ignorerà quei puntatori dir correnti e parent.

Si otterrà un errore se uno dei tre modelli *, [^.]*o ..?*partite alcun file, così si dovrebbe includere solo quelli che corrispondono.


Bello. Una risposta simile per questo stile di globbing è qui: superuser.com/a/784046/144977 . Grazie per aver pubblicato questo
Phyatt,

7

Due possibili soluzioni che mi vengono in mente. Il primo è usare cp invece con la sua opzione ricorsiva, copiando la directory corrente nella destinazione.

cp -Rp . /desired/directory

quindi è possibile rimuovere i file di origine nella directory corrente

In alternativa, se sai che i file hanno un nome sicuro (senza spazi, caratteri jolly, caratteri non stampabili), puoi fare qualcosa del genere

mv $(ls -A) /desired/directory

4
Copia-quindi-rimuovi è molto diverso da sposta se l'origine e la destinazione si trovano sullo stesso filesystem. Almeno includere l'opzione -pper conservare i metadati. L'uso lsdovrebbe essere l'ultima risorsa, e qui ci sono modi migliori e più semplici.
Gilles,

2

Non esistono file "nascosti" su Linux. I file che iniziano con un punto sono semplicemente nascosti dagli elenchi dei file per impostazione predefinita.

Per copiare i file anche con un glob, è necessario aggiungere il prefisso al file .come mv -u .* fooe quindi .fooapparirà come foo/.fooquando viene spostato.

L'opzione -u sposta i file solo quando l'origine è più recente o manca la destinazione. Oppure potresti semplicemente ignorare gli errori di spostamento .e ..poiché sono file speciali e non possono essere spostati, ma vengono catturati nel .*globo dalla shell.


Controlla le aggiunte che ho inserito in fondo alla mia domanda. Grazie.
Randall Cook,

0

Quindi abbiamo:

a
|-- .foo
`-- bar

e:

b

Ho preso un enorme tempo a trovare una soluzione migliore di tutte le risposte qui.

Quindi ho impiegato 30 secondi per questo comando:

$ mv --help

Poi ho trovato il mio amore:

$ mv a/ b/ -T

Nota: non capisco nemmeno l'argomento -T. Ha fatto proprio quello di cui avevo bisogno. Qui dice:

-T, --no-target-directory tratta DEST come un file normale


1
Se ometti le barre, non dovresti averne bisogno -T. In entrambi i casi, ciò sta essenzialmente dicendo a mv di spostare la directory stessa, anziché spostare tutti i file al suo interno.
thomasrutter,

@thomasrutter, spostare la directory stessa non equivale a rinominarla?
Randall Cook,

3
Sì, se la destinazione principale rimane invariata, è essenzialmente solo rinominandola. Comunque vi riferiate ad esso, probabilmente non aiuta a rispondere alla domanda originale, che riguardava lo spostamento dei file all'interno della directory in una data posizione.
thomasrutter,

0

Nel mio caso stavo semplicemente provando a mvun singolo file nascosto e questa era la soluzione:

FILE=.myHiddenFile
mv "$FILE" dest/

Spiegazione

All'inizio stavo provando:

mv .myHiddenFile dest/

Ma ha continuato a produrre l'errore:

mv: cannot stat '.myHiddenFile': No such file or directory

Anche se a ha ls -aldimostrato che il file ed dest/esisteva.

Il motivo sembra essere perché la shell stava interpretando il "." nel nome del file, quindi spostandolo in una variabile si evita l'interpretazione. Probabilmente ci sono altri modi per risolverlo, ma questo è stato sufficiente per noi.


-1

Se si desidera copiare i file inclusi i file nascosti nella directory corrente in cui ci si trova.

cp -Rp source-directory/. .

1
Questo è molto simile alla risposta di Drake Clarris del 2013. Hai altro da aggiungere?
Randall Cook,
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.