Copia di più file specifici da una cartella all'altra

106

Ho una grande cartella di immagini (migliaia) e ho un lungo elenco di file, con il nome esatto del file, che devo copiare in un'altra cartella. Voglio sapere se c'è un modo per selezionare diversi file specifici da questa cartella, per nome, e copiarli su un'altra cartella, usando il terminale, senza copiarli individualmente?

    
posta Someone with far too many pict 01.08.2013 - 07:44

4 risposte

150

Copia semplicemente più file contemporaneamente dalla riga di comando

Ci sono molti modi per riuscirci. Il più semplice che ho visto è quello di utilizzare il seguente.

cp /home/usr/dir/{file1,file2,file3,file4} /home/usr/destination/

La sintassi utilizza il comando cp seguito dal percorso della directory in cui si trovano i file desiderati con tutti i file che si desidera copiare racchiusi tra parentesi e separati da virgole.

Assicurati di notare che non ci sono spazi tra i file. L'ultima parte del comando, /home/usr/destination/ , è la directory in cui desideri copiare i file.

o se tutti i file hanno lo stesso prefisso ma finali diversi puoi fare qualcosa di simile a questo:

cp /home/usr/dir/file{1..4} ./

Dove file1, file2, file3 e file4 verrebbero copiati.

Da come hai formulato la domanda credo che questo sia ciò che stai cercando, ma sembra anche che tu stia cercando un comando per leggere da un elenco di file e copiarli tutti in una determinata directory. Se è il caso, fammelo sapere e modificherai la mia risposta.

Gestione dei duplicati con python

Quindi ho scritto un piccolo script in python che credo dovrebbe portare a termine il lavoro. Tuttavia, non sono sicuro di quanto tu sia esperto in python (se non lo avessi mai visto), quindi proverò a spiegare come usare questo script il meglio che posso e ti chiedo il maggior numero di domande a riguardo.

import os,sys,shutil
### copies a list of files from source. handles duplicates.
def rename(file_name, dst, num=1):
    #splits file name to add number distinction
    (file_prefix, exstension) = os.path.splitext(file_name)
    renamed = "%s(%d)%s" % (file_prefix,num,exstension)

    #checks if renamed file exists. Renames file if it does exist.
    if os.path.exists(dst + renamed):
        return rename(file_name, dst, num + 1)
    else:
        return renamed

def copy_files(src,dst,file_list):
    for files in file_list:
        src_file_path = src + files
        dst_file_path = dst + files
        if os.path.exists(dst_file_path):
            new_file_name =  rename(files, dst)
            dst_file_path = dst + new_file_name

        print "Copying: " + dst_file_path
        try:
            shutil.copyfile(src_file_path,dst_file_path)
        except IOError:
            print src_file_path + " does not exist"
            raw_input("Please, press enter to continue.")

def read_file(file_name):
    f = open(file_name)
    #reads each line of file (f), strips out extra whitespace and 
    #returns list with each line of the file being an element of the list
    content = [x.strip() for x in f.readlines()]
    f.close()
    return content

src = sys.argv[1]
dst = sys.argv[2]
file_with_list = sys.argv[3]

copy_files(src,dst,read_file(file_with_list))

Questo script dovrebbe essere relativamente semplice da usare. Prima di tutto, copia il codice sopra nel programma gedit (dovrebbe essere preinstallato in Ubuntu) o in qualsiasi altro editor di testo.

Dopo averlo completato, salva il file come move.py nella tua home directory (può essere una qualsiasi directory ma per facilità di istruzioni ti basta usare la home directory) o aggiungi la directory al file è contenuto nel tuo PERCORSO. Quindi cd alla tua home directory (o qualunque altra directory hai salvato move.py in) dal terminale e scrivi il seguente comando:

python move.py /path/to/src/ /path/to/dst/ file.txt

Questo dovrebbe copiare tutti i file che sono elencati dalla directory sorgente alla directory di destinazione con i duplicati prendendo il formato pic (1) .jpg, pic (2) .jpg e così via. file.txt dovrebbe essere un file che elenca tutte le immagini che desideri copiare con ciascuna voce sulla propria riga separata.

In nessun modo questo script dovrebbe influenzare la directory di origine, tuttavia assicurati di inserire i percorsi corretti per la directory di origine e di destinazione e il peggio che potrebbe accadere è copiare i file nella directory sbagliata.

Note

  • Questo script presuppone che tutte le immagini originali siano nella stessa maniera directory. Se vuoi che controlli anche le sottodirectory e lo script dovrà essere modificato.
  • Se per errore digita in modo errato un nome di file, lo script sputerà l'errore
    "il file non esiste" e ti chiede di "premere invio" per continuare e lo script continuerà a copiare il resto dell'elenco.
  • Non dimenticare la percentuale finale di co_de% su entrambi i percorsi verso il codice sorgente
    directory e percorso alla directory di destinazione. Altrimenti la sceneggiatura sputerà un errore a te.
risposta data Bryan 01.08.2013 - 08:04
32

Forse mi manca un dettaglio della tua domanda, ma le risposte date sembrano eccessive. Se vuoi una soluzione da riga di comando e non uno script, perché no:

cd /path/to/src/
cp -t /path/to/dst/ file1 file2 file3 ...

La cosa bella di farlo in questo modo è che puoi tablettere i nomi dei file completi

    
risposta data Ross Allen 25.08.2016 - 19:48
6

Ecco una soluzione bash pura. Legge i nomi dei file da un file di input (uno per riga) e ne copia ciascuno, rinominando i duplicati.

#!/usr/bin/env bash

## The destination folder where your files will
## be copied to.
dest="bar";

## For each file path in your input file
while read path; do 
    ## $target is the name of the file, removing the path. 
    ## For example, given /foo/bar.txt, the $target will be bar.txt.
    target=$(basename "$path"); 
    ## Counter for duplicate files
    c=""; 
    ## Since $c is empty, this will check if the
    ## file exists in target.
    while [[ -e "$dest"/"$target"$c ]]; do
        echo "$target exists"; 
        ## If the target exists, add 1 to the value of $c
        ## and check if a file called $target$c (for example, bar.txt1)
        ## exists. This loop will continue until $c has a value
        ## such that there is no file called $target$c in the directory.
        let c++; 
        target="$target"$c; 
    done; 
    ## We now have everything we need, so lets copy.
    cp "$path" "$dest"/"$target"; 
done

Salva questo script in una cartella in $PATH e chiamalo con l'elenco di percorsi come input:

auto_copy.sh < file_paths.txt

Puoi anche eseguire l'intera cosa come comando dal terminale:

while read path; do 
   target=$(basename "$path"); 
   c=""; 
   while [[ -e bar/"$target"$c ]]; do 
    echo "$target exists"; 
    let c++; 
    target="$target"$c; 
   done; 
   cp "$file" bar/"$target"; 
done < file_names;
    
risposta data terdon 01.08.2013 - 17:24
0

Come da descrizione della domanda, la mia comprensione è che:

  • c'è una lista di file, presumibilmente un file di testo input.txt
  • l'elenco contiene solo nomi di file
  • c'è una particolare directory in cui si trovano questi nomi di file.

Quindi, si può usare il seguente comando:

xargs -I % --arg-file=input.txt cp  /path/to/origin_dir/%  /path/to/destination

Spiegazione:

  • -I % specifica il simbolo per il file attualmente elaborato da utilizzare all'interno del comando
  • --arg-file=input.txt specifica di assumere argomenti da comandare da input.txt
  • cp /path/to/origin_dir/% /path/to/destination/ eseguirà il comando cp con /path/to/origin_dir/% sostituito con /path/to/origin_dir/ e il nome del file attualmente elaborato.

Esempio pratico:

$ cat input.txt
file2.txt
file1.txt
file3.txt
$ ls ./docs
file1.txt  file2.txt  file3.txt
$ xargs -I % --arg-file=input.txt cp ./docs/% ./docs_destination/
$ ls ./docs_destination/
file1.txt  file2.txt  file3.txt
    
risposta data Sergiy Kolodyazhnyy 26.05.2018 - 09:32

Leggi altre domande sui tag