Come spostare tutti i file dalla directory corrente alla directory superiore?


133

Come spostare tutti i file dalla directory corrente alla directory superiore in Linux?

Ho provato qualcosa del genere mv *.*, ma non funziona.


Non ho abbastanza rappresentante per ripetere la domanda, ma posso suggerire [linux] [mv] [cwd] [files]qualcosa di simile?
Stephan202,

Ho ricodificato questa domanda per la richiesta di Stephan202.
undici81,

Risposte:


202

Il comando che stai cercando è

mv * .[^.]* ..

oppure (vedi sotto per maggiori informazioni):

(shopt -s dotglob; mv -- * ..)

Spiegazione: il mvcomando sposta file e directory. L'ultimo argomento a mvè la destinazione (in questo caso la directory un passo "su" nella struttura ad albero ..). Gli argomenti precedenti sono i file e le directory di origine. L'asterisco ( *) è un carattere jolly che corrisponde a tutti i file che non iniziano con un punto. I file che iniziano con un punto (dotfile) sono "nascosti". Sono abbinati usando il modello .[^.]*(vedi modifica sotto).

Vedi la manpage che ho collegato per maggiori informazioni mv.


Perché .[^.]*invece di .*?

Come sottolinea correttamente Chris Johnsen : anche il modello .*corrisponde .e ... Dato che non vuoi (e non puoi) spostarli, è meglio usare un modello che corrisponda a qualsiasi nome di file che inizia con un punto tranne quei due . Il modello .[^.]*fa proprio questo: corrisponde a qualsiasi nome di file (1) che inizia con un punto (2) seguito da un carattere che non è un punto (3) seguito da zero o più caratteri arbitrari.

Come sottolinea Paggas , dovremmo anche aggiungere il modello per abbinare i file che iniziano con due punti. Vedi la sua risposta per una soluzione alternativa che utilizza ..??*find

La risposta di Arjan menziona shoptal fine di evitare tutti quei problemi con dotfile. Ma poi c'è ancora il problema con i file che iniziano con un trattino. E richiede tre comandi. Comunque, mi piace l'idea. Propongo di usarlo in questo modo:

(shopt -s dotglob; mv -- * ..)

Questo viene eseguito shoptin una subshell (quindi nessuna seconda chiamata a shoptrichiesta) e utilizza in --modo che i file che iniziano con un trattino non vengano interpretati come argomenti mv.


7
L'uso .*potrebbe far sì che mv produca avvisi / errori in merito alla mancata possibilità di spostamento .e ... Potresti provare mv * .[^.]* ..invece.
Chris Johnsen,

1
@alain: prego, benvenuto nel sito! (Se (e solo se) uno dei post qui ha risposto sufficientemente alla tua domanda, allora puoi contrassegnarlo come tale. Ciò otterrà il poster 15 punti reputazione extra e ti darà anche 2 rep extra.)
Stephan202

Mi piace molto la soluzione
shopt

2
Non vi è alcun danno nella sintassi *. * - incluso .. è pericoloso solo se usato con chmod e chown e il flag "recurse", cioè chmod -R o chown -R. E in questi casi, non digitare mai chown. * O chmod. * - chown la directory principale nel percorso che stai cercando e usa -h (non seguire i collegamenti simbolici). Ma, mv .. semplicemente non fa nulla, quindi non preoccuparti.
chris,

1
I tre modelli corretti sono *, .[^.]*e ..?*. Il secondo forse .[!.]*per le shell più vecchie (POSIX). Leggi anche

42

Risposta breve: usare

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

Risposta lunga:

Il comando

mv * .* ..

non funzionerà poiché .*può corrispondere .e ... Ma il comando

mv * .[^.]* ..

inoltre non funzionerà, poiché .[^.]*non corrisponderà, ad es. ..filename! Invece, quello che faccio è

mv * .[^.] .??* ..

che corrisponderà a tutto tranne .e ... *corrisponderà a tutto ciò che non inizia con a ., .[^.]corrisponderà a tutti i nomi di file di 2 caratteri che iniziano con un punto tranne .., e .??*corrisponderà a tutti i nomi di file che iniziano con un punto di almeno 3 caratteri.

Meglio ancora, puoi usare

find . -mindepth 1 -maxdepth 1 -exec mv -t.. -- {} +

che evita i brutti attacchi di glob mv * .[^.] .??* ..!


1
Inoltre, ho dimenticato di notare l'importanza di - in modo che il comando funzioni correttamente con i nomi dei file che iniziano con un trattino. Ho incluso - nella mia risposta di ricerca però. Una risposta più completa con globs è "mv - *. [^.]. ?? * ..".
Paggas,

+1: sono tornato per aggiungere ..?*al mio commento e te ne eri già occupato.
Chris Johnsen,

1
Cosa può esserci di sbagliato nel provare a mv ..? Semplicemente non fa nulla e non può fare nulla. Ci sono altri comandi in cui può fare qualcosa (chmod e chown) ma mv e rm semplicemente non fanno nulla per. oppure ...
chris,

1
Questo dà a mv: opzione illegale - t
pal4life il

1
Bono, i doppi trattini dicono mvdi smettere di cercare ulteriori opzioni di comando. Le parentesi graffe sono un nome file risultante. Il segno più indica invece di eseguire exec per risultato (es. Per nome file), inserire quanti più risultati in un singolo exec possibile. Per completezza, -t..sta dicendo di spostare la destinazione di destinazione in cui spostare tutti questi file.
Isuldor,

14

Solo per completezza, si può anche dire alla shell Bash di includere file nascosti, usando shopt:

shopt -s dotglob
mv -- * ..
shopt -u dotglob

+1. Molto più pulito. Penso che sia in atto un leggero miglioramento. Vedi l'aggiornamento alla mia risposta.
Stephan202,

8

Il mv non ha la funzionalità di spostare i file nascosti quando si usa *- quindi perché non usare copia invece?

cp -rf . ..

rm -rf *

Non è necessario entrare in soluzioni complesse di dotglobbing e utilizzare i comandi find.


Avvertenza Se ci si sposta nello stesso filesystem , nella maggior parte dei casi non è stato realmente copiato il file ma si è aggiornato solo le voci della directory senza spostare l'inode o il contenuto del file. Vedi anche [1 ]. Con un cpe rminvece stai davvero copiando tutto.
Hastur,

6
rsync -a --remove-source-files . ..

rsync è uno strumento di copia dei file estremamente potente, generalmente utilizzato per eseguire backup e mirror remoti incrementali efficienti.

Con il comando sopra, stiamo dicendo rsyncdi copiare il contenuto di .in..

Lo switch -aabilita la ricorsione in .sottodirectory e abilita alcune altre opzioni comuni.

Lo switch --remove-source-filesdice a rsync di rimuovere i file sorgente dopo una copia corretta, ovvero fa sì che rsync si comporti in modo simile al mvcomando.


1
Una spiegazione in più sarebbe piacevole.
ChrisF,

Certo, spero sia più chiaro ora.
mrucci,

Si noti che --remove-source-filesnon rimuoverà le directory (sincronizzate).
Dennis,

Una buona soluzione accettata mi dà un -bash: /bin/mv: Argument list too longerrore. Questo funziona come il fascino.
userlond

2

Alla fine il tentativo mv .fallirà perché mv non sarà in grado di scollegare la directory in cui ci si trova attualmente. È possibile mv * ..spostare i file nel CWD.


2
mv * .??* ../.

*ottiene tutti i file non a punti. .??*ottiene tutto. file lunghi almeno tre byte, che funzionano per tutti quelli legittimi. Qualunque cosa ti sia rimasta, probabilmente vuoi rmpiuttosto che mvcomunque.

Il ../. non offre alcun beneficio diretto sopra .., ma quando si fa una mossa-to-directory che è una buona abitudine per entrare, perché fallirà, come si vuole, se c'è qualcosa di sbagliato con il percorso. Ad esempio, mv xyz bletchdove pensi che bletch sia una directory, puoi essere più sicuro con mv xyz bletch/..


2
Potresti aggiungere .[^.]per ottenere file di copertina come .a.
Chris Johnsen,

Non c'è differenza tra ../ e ../. quindi non mi preoccuperei di digitare il. dopo la barra. Inoltre, nel caso di mv e rm, non fa male includere. e .. nell'elenco, cioè non c'è nulla di spaventoso o sbagliato in mv *. * / path / to / file /, proprio come rm. o anche -rf. non fa niente.
chris,

2

Questo comando minimizzato funziona sulla maggior parte delle shell moderne:

\mv -- {,.{[^.],??}}* ..

Altrimenti menzionato è una soluzione portatile:

\mv -- * .[^.] .??* ..

Caratteristiche:

  1. \ impedisce agli alias di alterare indesiderabilmente mv.

  2. - impedisce che i nomi di file contenenti trattini iniziali (-xyz) vengano interpretati come argomenti della riga di comando.

  3. . [^.] corrisponde a tutti e due i nomi dei file dei caratteri che iniziano con. tranne ..

  4. . ?? * corrisponde a tutti gli altri nomi di file di tre caratteri o più.

Implementazioni ingenui:

  1. Di seguito vengono ignorati i nomi file UNIX nascosti, quelli che iniziano con. (.Bashrc).

    mv * ..
    
  2. Le seguenti corrispondenze .. che tentano in modo ricorsivo di spostare tutte le directory alla fine in / in .. della directory di lavoro corrente ($ PWD o pwd). Non usare mai

    mv .* ..
    

2

È più corretto usare il modello * .[!.] .??*che da * .[^.] .??*quando il primo funzionerà anche con shell più vecchie come ksh88:

mv -- * .[!.] .??* ..
  • -- impedisce problemi quando si dispone di un nome file che inizia con -
  • * corrisponde a tutti i nomi di file che non iniziano con a .
  • non ci sono nomi di file di un carattere che iniziano con un .che puoi / dovresti spostare
  • .[!.] corrisponde a tutti e due i nomi dei file dei caratteri che iniziano con a .
  • .??* corrisponde a tutti e tre i nomi dei file di caratteri (o più lunghi) che iniziano con a .

Con ksh88, il modello del nome file .[^.]corrisponderà infatti ai nomi dei file ..(che esiste sempre) e .^(che probabilmente non esiste), con un effetto opposto a quello desiderato.


0

Trova e grep funzionano anche. Questo tipo di struttura potrebbe essere utile se si desidera selezionare i file su criteri più complicati modificando find ed egrep.

find -maxdepth 1 | egrep '^./.'         # Returns all files

mv `find -maxdepth 1 | egrep '^./.'` .. # mv <all files> ..

0

Penso che la soluzione più semplice per spostare tutti i file nella sua directory principale. sarebbe

mv "`ls`" ../

oppure, se ci sono file / directory nascosti

uso:

mv "`ls -a`" ../ 2>/dev/null

Inoltre, supponiamo che tu voglia spostare il contenuto di alcune cartelle in una delle sue cartelle interne tony (diciamo)

uso:

mv "`ls -a`" /tony 2>/dev/null

Nota:

"`ls -a`" 

Per spostare i file che contengono spazi.

2>/dev/null

Serve a sopprimere l'avviso / errore perché ls -astampa il .e.. cartella come bene e non è possibile spostare o copiare loro. Quindi per quelle cartelle mostrerà un errore (se non usiamo 2> / dev / null) che non può spostarle e il resto verrà spostato abbastanza comodamente.

Meglio evitare ls -ase non ci sono file nascosti e basta usare ls.


Hai provato cosa succederà quando corri mv $(ls -a)? Ciò toccherebbe la directory corrente e la directory sottostante, perché anche l' ls -aoutput verrà emesso ...
Sami Laine,

Grazie, @SamiLaine per il suggerimento che ho apportato le correzioni. Ma mv ls -a ../avrebbe anche funzionato secondo necessità, Sì, mostrerà quegli errori come ho detto sopra, ma a parte questo, sposterà le cartelle / i file richiesti nella directory principale.
Prabhat Kumar Singh,

Questo non funzionerà per i file con spazi.
Kenorb,

@kenorb è necessario citare due volte il lscomando per spostare i file con spazi. Ho apportato le modifiche richieste. Grazie per averlo segnalato.
Prabhat Kumar Singh,
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.