Come spostare tutti i file inclusi i file nascosti nella directory principale tramite *


113

Deve essere una domanda popolare ma non sono riuscito a trovare una risposta.

Come spostare tutti i file tramite * inclusi anche i file nascosti nella directory principale in questo modo:

mv /path/subfolder/* /path/

Questo sposterà tutti i file nella directory principale come previsto ma non sposterà i file nascosti. Come farlo?


1
questa domanda ha un duplicato in SU , con una risposta ancora più corretta (non quella accettata però): cp -r /path/to/source/. /destination
Florian

Risposte:


202

Puoi trovare una serie completa di soluzioni su questo nella risposta di UNIX e Linux a Come sposti tutti i file (inclusi quelli nascosti) da una directory all'altra? . Mostra le soluzioni in Bash, zsh, ksh93, standard (POSIX) sh, ecc.


Puoi usare questi due comandi insieme:

mv /path/subfolder/* /path/   # your current approach
mv /path/subfolder/.* /path/  # this one for hidden files

O tutti insieme ( grazie pfnuesel ):

mv /path/subfolder/{.,}* /path/

Che si espande a:

mv /path/subfolder/* /path/subfolder/.* /path/

(esempio: si echo a{.,}bespande in a.b ab)

Nota che questo mostrerà un paio di avvertimenti:

mv: cannot move ‘/path/subfolder/.’ to /path/.’: Device or resource busy
mv: cannot remove /path/subfolder/..’: Is a directory

Ignorateli semplicemente: questo accade perché /path/subfolder/{.,}*si espande anche in /path/subfolder/.e /path/subfolder/.., che sono la directory e la directory principale (vedere Cosa significano “.” E “..” quando ci si trova in una cartella? ).


Se vuoi solo copiare, puoi usare un semplice:

cp -r /path/subfolder/. /path/
#                     ^
#                     note the dot!

Questo copierà tutti i file, sia quelli normali che quelli nascosti, poiché si /path/subfolder/.espande in "tutto da questa directory" (Fonte: come copiare con cp per includere file nascosti e directory nascoste e il loro contenuto? )


2
Le parentesi graffe sono solo una scorciatoia mv /path/subfolder/* /path/subfolder/.* /path/, non strettamente necessaria per combinare i due comandi in uno.
chepner

7
Ottengo il seguente errore:mv: overwrite `/path/.'? y mv: cannot move `/path/subfolder/.' to `/path/.': Device or resource busy mv: overwrite `/path/..'? y mv: cannot move `/path/subfolder/..' to `/path/..': Device or resource busy
Dejan

@Dejan Basta ignorarlo. .denota la directory corrente e ..denota la updirectory. Avrai notato che tutti gli altri file vengono spostati.
Debiprasad

Vale la pena ricordare che la scorciatoia tra parentesi graffe non funzionerà per tutte le shell, ma penso che il comando @chepner lo farà
Jesús Carrera,

7
"Ignora solo l'avvertimento" potrebbe non essere sempre una buona idea. In questo momento sto riscontrando un problema con uno script in cui devo interrompere l'esecuzione se un passaggio non riesce, poiché questa soluzione causa sempre un errore, uccide il mio script. Ho bisogno di un modo per determinare se il comando mv è fallito o meno ...
MarioVilas

29

Penso che questo sia il più elegante, in quanto inoltre non cerca di muoversi ..:

mv /source/path/{.[!.],}* /destination/path

1
sì, ho notato che dava anche quei messaggi di errore, bella scoperta.
Joseph Astrahan

Penso che questa sia un'ottima soluzione ma è piuttosto difficile ricordare quello schema
Dylan B

questo mancherebbe file come ..anythingo ...anythingecc. - stackoverflow.com/a/31438355/2351568 contiene la regex corretta per questo problema. || ma comunque l'utilizzo shopt -s dotglobè ancora la soluzione migliore!
DJCrashdummy

@ DylanB non memorizzarlo. ricorda che corrisponde a tutto ciò che è nelle parentesi graffe, separato da virgole. {a,b}*troverebbe tutti i file che iniziano con aob come "anatomy" e "bulldozer". La seconda corrispondenza è solo una corrispondenza vuota, equivalente a *, e la prima corrispondenza è equivalente a .[!.], dove il gruppo [!.]indica un gruppo che NON inizia con a .. Questo significa .*ma non ..*.
mazunki

28

Questo sposterà tutti i file nella directory principale come previsto ma non sposterà i file nascosti. Come farlo?

Potresti attivare dotglob:

shopt -s dotglob               # This would cause mv below to match hidden files
mv /path/subfolder/* /path/

Per disattivare dotglob, dovresti dire:

shopt -u dotglob

Molto utile. Volevo saperne di più, ma shopt è un builtin quindi man shoptnon funziona ed help shoptè molto breve. Ma puoi fare bashman () { man bash | less -p "^ $1 "; }e poi bashman shoptleggere tutto in modo semplice. (Potrebbe essere necessario premere n per passare al comando se ci sono righe che iniziano con shopt, come ho scoperto.)
Nick Rice

2
questo influenzerà anche tutti gli altri comandi come ls.. quindi non proprio quello che vorresti, probabilmente
phil294

5

Una soluzione alternativa più semplice consiste nell'usare l' rsyncutilità:

sudo rsync -vuar --delete-after --dry-run path/subfolder/ path/

Nota: il comando sopra mostrerà cosa verrà modificato. Per eseguire le modifiche effettive, rimuovere--dry-run .

Il vantaggio è che la cartella originale ( subfolder) verrebbe rimossa così come parte del comando, e quando si utilizzano mvesempi qui è comunque necessario ripulire le cartelle, per non parlare del mal di testa aggiuntivo per coprire i file nascosti e non nascosti in un unico modello.

Inoltre rsyncfornisce il supporto per copiare / spostare file tra telecomandi e farebbe in modo che i file vengano copiati esattamente come erano originariamente ( -a).

Il -uparametro utilizzato salterebbe i file più recenti esistenti, -rricorrerebbe alle directory e -vaumenterebbe la verbosità.


La migliore soluzione in assoluto! Nel mio caso ho appena rimosso il parametro -u, perché non vorrei aggiornare la cartella principale. Grazie
Thales Ceolin

Questo è uno di quei comandi in cui se non stai attento, puoi davvero rovinare le cose per te stesso in Linux, in modo permanente. Aggiorna la tua risposta per includere sudo prima del comando rsync, altrimenti gli utenti possono facilmente ottenere l'autorizzazione negata per mkdir, ma le eliminazioni dei file andranno comunque avanti, quindi il comando rsync eliminerà l'intera directory che desideri spostare e non farà nient'altro . Perderai l'intera directory. Una volta aggiunto sudo alla tua risposta, questa dovrebbe probabilmente essere la risposta accettata. Quindi il comando dovrebbe essere: sudo rsync -vuar --delete-after path / subfolder / path /
Blue Water

@ JohnnyB Ci scusiamo per l'inconveniente. Ho aggiunto sudoe --dry-run, quindi le persone possono testare le modifiche prima di eseguire il comando effettivo al fine di evitare potenziali problemi.
Kenorb

Oh, non mi ero reso conto che ci fosse un'opzione - corsa a secco. Buona aggiunta. Non c'è bisogno di scuse. Questo è eccellente.
Blue Water il

3

Lascia che ti presenti il ​​mio amico "dotglob". Si accende e si spegne indipendentemente dal fatto che "*" includa file nascosti.

$ mkdir test
$ cd test
$ touch a b c .hidden .hi .den
$ ls -a
. ..  .den  .hi .hidden a b c

$ shopt -u dotglob
$ ls *
a b c
$ for i in * ; do echo I found: $i ; done
I found: a
I found: b
I found: c

$ shopt -s dotglob
$ ls *
.den  .hi .hidden a b c
$ for i in * ; do echo I found: $i ; done
I found: .den
I found: .hi
I found: .hidden
I found: a
I found: b
I found: c

Il valore predefinito è "off".

$ shopt dotglob
dotglob         off

È meglio riaccenderlo quando hai finito altrimenti confonderai le cose che presumono che sarà spento.


3

Utilizzando il findcomando insieme al mvcomando, è possibile impedire al mvcomando di tentare di spostare directory (ad esempio ..e .) e sottodirectory. Ecco un'opzione:

find /path/subfolder -maxdepth 1 -type f -name '*' -exec mv -n {} /path \;

Ci sono problemi con alcune delle altre risposte fornite. Ad esempio, ciascuno dei seguenti tenterà di spostare le sottodirectory dal percorso di origine:

1) mv /path/subfolder/* /path/ ; mv /path/subfolder/.* /path/
2) mv /path/subfolder/{.,}* /path/ 
3) mv /source/path/{.[!.],}* /destination/path

Inoltre, 2) include l'estensione. e .. file e 3) manca file come ..foobar, ... barfoo, ecc.

Potresti usare,, mv /source/path/{.[!.],..?,}* /destination/pathche includerebbe i file persi per 3), ma proverebbe comunque a spostare le sottodirectory. Usare il findcomando con il mvcomando come ho descritto sopra elimina tutti questi problemi.


2

La mia soluzione per questo problema quando devo copiare tutti i file (inclusi i .file) in una directory di destinazione mantenendo le autorizzazioni è: (sovrascrivi se esiste già)

yes | cp -rvp /source/directory /destination/directory/

yesserve per sovrascrivere automaticamente i file di destinazione, rricorsivi, vdettagliati, pmantenere le autorizzazioni.

Notare che il percorso di origine non termina con a/ (quindi tutti i file / directory e .file vengono copiati)

La directory di destinazione termina con/ poiché stiamo posizionando il contenuto della cartella di origine nella destinazione nel suo insieme.


Sebbene yessia un comando fantastico da usare se vuoi sovrascrivere i file di destinazione, non è sempre desiderato. Usalo solo se sei sicuro di volerlo fare. Inoltre, c'è una differenza tra yes | cp ...e cp -f ...?
mazunki
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.