Spostare una lista di file (in un file di testo) in una directory?


7

Ho una lista di file, con i loro percorsi completi, uno per riga in un file "files.txt"

Stavo cercando di spostare tutti quei file dalla loro posizione originale in una nuova directory.

Ho inserito la cartella nella directory in cui vivono ora e pubblicata

for file in ~/Desktop/files.txt do mv $file ~/newfolder

ma non succede nulla. Sono sicuro che mi manca qualcosa di ovvio


1
Hai bisogno di alcuni separatori, prova a farlo solo con: for file in ~/Desktop/files.txt; do echo $file; done.
nerdwaller

1
@nerdwaller che non funzionerà, bash stamperà semplicemente "~ / Desktop / files.txt", non leggerà il file se non esplicitamente detto a for n in $(cat files.txt); do something; done o while read n; do something; done < files.txt.
terdon

@terdon, volevo modificarlo quando ho realizzato che ero su un autopilota non pensante ma era scaduto. Grazie per averlo indicato e fornito la correzione :)
nerdwaller

Risposte:


7

bash non leggerà il contenuto del file a meno che tu non lo dica.

for file in $(cat ~/Desktop/files.txt); do mv "$file" ~/newfolder; done

Se questo è su una singola riga, avresti bisogno ; fra $() e do.
nerdwaller

1
@nifle Funzionerebbe se i file avessero tutti percorsi diversi, quando un percorso potrebbe essere /Users/lombardi/work files/myfile.png e un altro nello stesso file.txt /docs/file.jpg?
Steve

2
Uso inutile di cat, e il tuo script si rompe in molti modi, anche se un file contiene solo uno spazio nel suo percorso. Si prega di risolvere questo, come questo tipo di una causa comune per i problemi.
slhck

@ slhck - Non sono d'accordo sul useless use of cat dogma, specialmente per una nave come questa. Scoprire cosa fa il gatto se non si è familiari è semplice, cercare di capire cosa < ~/Desktop/files.txt non è così semplice.
Nifle

3
Ciò si interrompe ancora sui nomi di file che contengono spazi. Da IFS è impostato su qualsiasi spazio bianco, come un nome di file Quarterly report.pdf fallirà sopra, nonostante $file è quotato, dal momento che Bash dividerà gli argomenti del ciclo sullo spazio: prima $file conterrà "Quarterly" e nella prossima iterazione che conterrà "report.pdf". Una soluzione è impostare IFS='\n', ma esiste già una soluzione sicura < files.txt versione. Questo è uno dei motivi per cui non è bello imparare le persone a fare il ciclo in questo modo, dal momento che volontà rompere prima o poi.
Daniel Andersson

6

Devi dire al tuo ciclo di leggere il file, altrimenti è solo in esecuzione:

mv ~/Desktop/files.txt ~/newfolder

Inoltre, come diceva nerdwaller, hai bisogno di separatori. Prova questo:

while read file; do mv "$file" ~/newfolder; done < ~/Desktop/files.txt

Se i percorsi oi nomi dei file contengono spazi o altri caratteri strani, potrebbe essere necessario effettuare questa operazione:

while IFS= read -r file; do mv "$file" ~/newfolder; done < ~/Desktop/files.txt

Notare le virgolette " attorno a $file variabile.


Grazie per aver modificato il mio, mi sono reso conto del mio errore ma non ero in grado di correggere (limite di modifica del commento) e stavo scrivendo una risposta quando il tuo è comparso. Grazie!
nerdwaller

Grazie, anche questo funziona, ma ho trovato l'altro post per essere più facile da ricordare per il futuro.
Steve

Nessun problema, sono entrambi corretti.
terdon

Stavo per fare la stessa modifica come hai fatto tu, grazie :) (Scusa, è solo che ci sono così molti "buoni" o per lo più sbagliati Bash si aggira su Internet ...)
slhck

1
Sì, ho appena controllato. Con while, funziona un po 'bene. È solo il -r l'opzione deve essere utilizzata per conservare i backslash e le impostazioni IFS= fa read non tagliare nessuno spazio iniziale o finale. Suo for ciò causa problemi. Vedere: Non leggere le righe con per
slhck

3

Se i nomi file non contengono spazi vuoti:

mv -t dest_dir $(< text.file)

è probabilmente il modo più conciso.

Se ci sono spazi bianchi nei nomi dei file

while IFS= read -r filename; do mv "$filename" dest_dir; done < test.file

è salvo.


Il comando mv supporta solo il flag -t sui sistemi con la versione GNU di mv; questa versione non funzionerà su OS X o derivati ​​non-GNU UNIX.
Craig Finch

0

Possibilmente

mv -t dest_dir $(sed 's|^|"|;s|$|"|' text.file)

si occupa anche di nomi di file con spazi mentre utilizza ancora un singolo comando mv e nessun ciclo. Non testato.


Ci sono altre tre risposte, tutte potenziate e una accettata. Questa risposta è un codice non spiegato che hai etichettato come non testato. Perché qualcuno dovrebbe usare questa risposta?
fixer1234

0

Prova questo:

python -c "import shutil; [shutil.move (_. strip (), 'new') per _ in open ('files.txt'). readlines ()];"


(1) Puoi spiegare questo? (E l'hai provato?) (2) Questo ha qualche vantaggio rispetto alle altre risposte? ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... Pleasedonot rispondere agli incidenti; modificare la tua risposta sarà più chiara e completa.
Scott
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.