Copier plusieurs fichiers spécifiques d'un dossier à un autre

95

J'ai un grand dossier d'images (en milliers) et j'ai une longue liste de fichiers, par nom de fichier exact, que je dois copier dans un autre dossier. Je veux savoir s'il existe un moyen de sélectionner plusieurs fichiers spécifiques de ce dossier, par nom, et de les copier dans un autre dossier, en utilisant le terminal, sans les copier individuellement?

    
posée Someone with far too many pict 01.08.2013 - 07:44
la source

4 réponses

131

Copiez simplement plusieurs fichiers à la fois depuis la ligne de commande

Vous pouvez y parvenir de plusieurs manières. Le plus simple que j'ai vu est d'utiliser ce qui suit.

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

La syntaxe utilise la commande cp suivie du chemin du répertoire dans lequel se trouvent les fichiers souhaités avec tous les fichiers que vous souhaitez copier, entre crochets et séparés par des virgules.

Notez bien qu'il n'y a pas d'espace entre les fichiers. La dernière partie de la commande, /home/usr/destination/ , correspond au répertoire dans lequel vous souhaitez copier les fichiers.

ou si tous les fichiers ont le même préfixe mais des terminaisons différentes, vous pouvez faire quelque chose comme ceci:

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

Où fichier1, fichier2, fichier3 et fichier4 seraient copiés.

D'après votre façon de formuler la question, je pense que c'est ce que vous recherchez, mais il semblerait également que vous recherchiez une commande à lire dans une liste de fichiers et que vous les copiez tous dans un répertoire donné. Si tel est le cas, faites le moi savoir et je vais modifier ma réponse.

Traitement des doublons avec python

J'ai donc écrit un petit script python qui, je crois, devrait faire le travail. Cependant, je ne suis pas sûr de savoir à quel point vous êtes bien en python (si vous le savez), alors je vais essayer d'expliquer comment utiliser ce script du mieux que je peux et poser autant de questions que nécessaire.

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))

Ce script devrait être relativement simple à utiliser. Tout d'abord, copiez le code ci-dessus dans le programme gedit (devrait être pré-installé dans Ubuntu) ou tout autre éditeur de texte.

Une fois cette opération terminée, enregistrez le fichier sous move.py dans votre répertoire personnel (il peut s'agir de n'importe quel répertoire mais, pour faciliter les instructions, utilisez simplement le répertoire personnel) ou ajoutez le répertoire du fichier. est contenu dans votre PATH. Ensuite, cd dans votre répertoire personnel (ou dans le répertoire que vous avez enregistré move.py) à partir du terminal et tapez la commande suivante:

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

Cela devrait copier tous les fichiers listés du répertoire source vers le répertoire de destination avec les doublons prenant le format pic (1) .jpg, pic (2) .jpg et ainsi de suite. fichier.txt devrait être un fichier répertoriant toutes les images que vous souhaitez copier avec chaque entrée de sa propre ligne distincte.

Ce script ne doit en aucun cas affecter le répertoire source, mais assurez-vous d’entrer les chemins corrects vers le répertoire source et destination. Le pire, c’est que vous copiez les fichiers dans le mauvais répertoire.

Notes

  • Ce script suppose que toutes les images originales sont dans le même annuaire. Si vous voulez qu'il vérifie les sous-répertoires ainsi que le script devra être modifié.
  • Si vous confondez accidentellement un nom de fichier, le script va cracher l'erreur
    "fichier n'existe pas" et vous invite à "appuyer sur Entrée" pour continuer et le script continuera à copier le reste de la liste.
  • N'oubliez pas le / final à la fois sur le chemin d'accès à la source
    répertoire et chemin d'accès au répertoire de destination. Sinon le script va cracher une erreur sur vous.
réponse donnée Bryan 01.08.2013 - 08:04
la source
26

Peut-être me manque-t-il un détail de votre question, mais les réponses données semblent excessives. Si vous voulez une solution en ligne de commande et non un script, pourquoi pas:

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

La bonne chose à faire de cette façon est que vous pouvez compléter les noms de fichiers

    
réponse donnée Ross Allen 25.08.2016 - 19:48
la source
6

Voici une solution de base pure. Il lit les noms de fichiers à partir d’un fichier d’entrée (un par ligne) et copie chacun d’eux, en renommant les doublons.

#!/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

Enregistrez ce script dans un dossier dans votre $PATH et appelez-le avec la liste des chemins en entrée:

auto_copy.sh < file_paths.txt

Vous pouvez également exécuter le tout en tant que commande depuis le terminal:

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;
    
réponse donnée terdon 01.08.2013 - 17:24
la source
0

Selon la description de la question, je comprends que:

  • il y a une liste de fichiers, probablement un fichier texte input.txt
  • la liste contient uniquement les noms de fichiers
  • il existe un répertoire particulier où se trouvent ces noms de fichiers.

Ainsi, on peut utiliser la commande suivante:

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

Explication:

  • -I % spécifie le symbole du fichier actuellement traité à utiliser dans la commande
  • --arg-file=input.txt spécifie de prendre des arguments à la commande depuis input.txt
  • cp /path/to/origin_dir/% /path/to/destination/ exécutera la commande cp avec /path/to/origin_dir/% remplacé par /path/to/origin_dir/ et le nom du fichier actuellement traité.

Exemple pratique:

$ 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
    
réponse donnée Sergiy Kolodyazhnyy 26.05.2018 - 09:32
la source

Lire d'autres questions sur les étiquettes