web-dev-qa-db-fra.com

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

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 souhaite savoir s’il est possible de sélectionner plusieurs fichiers spécifiques dans ce dossier, par leur nom, et de les copier dans un autre dossier à l’aide du terminal, sans les copier individuellement.

Copiez simplement plusieurs fichiers à la fois à partir de 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 d'accès au répertoire dans lequel se trouvent les fichiers souhaités. Tous les fichiers que vous souhaitez copier sont entourés de crochets et séparés par des virgules.

Assurez-vous de noter qu'il n'y a pas d'espace entre les fichiers. La dernière partie de la commande, /home/usr/destination/, est le 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.

De la manière dont vous avez formulé la question, je pense que c’est ce que vous recherchez, mais il semble également que vous cherchiez peut-être une commande à lire dans une liste de fichiers et à les copier tous dans un répertoire donné. Si tel est le cas, faites le moi savoir et je modifierai ma réponse.

Traiter les doublons avec python

J'ai donc écrit un petit script python qui, selon moi, devrait permettre d'accomplir ce travail. Cependant, je ne suis pas sûr de votre niveau de connaissance de python (si je le connais bien). Je vais donc essayer d'expliquer comment utiliser ce script du mieux que je peux et s'il vous plaît posez autant de questions que vous le souhaitez. .

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 (doit être pré-installé dans Ubuntu) ou dans n’importe quel autre éditeur de texte.

Une fois l’opération terminée, enregistrez le fichier sous le nom move.py dans votre répertoire personnel (il peut s’agir de n’importe quel répertoire, mais pour plus de commodité, utilisons simplement le répertoire personnel) ou ajoutez le répertoire dans lequel se trouve le fichier. à votre chemin. Puis cd dans votre répertoire personnel (ou le répertoire dans lequel 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 doit copier tous les fichiers répertoriés du répertoire source dans le répertoire de destination avec les doublons au format pic (1) .jpg, pic (2) .jpg, etc. fichier.txt devrait être un fichier qui répertorie toutes les images que vous souhaitez copier avec chaque entrée sur une ligne distincte.

Ce script ne doit en aucun cas affecter le répertoire source. Toutefois, assurez-vous de saisir les chemins d'accès corrects aux répertoires source et de destination. Le pire qui puisse arriver est de copier les fichiers dans le mauvais répertoire.

Remarques

  • Ce script suppose que toutes les images d'origine se trouvent dans le même répertoire. Si vous souhaitez également vérifier les sous-répertoires, vous devez modifier le script.
  • Si vous tapez un nom de fichier par erreur, le script génère le message d'erreur.
    "le 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 / à la fin du chemin d'accès à la source
    répertoire et chemin d'accès au répertoire de destination. Sinon, le script vous créera une erreur.
165
Bryan

Il me manque peut-être un détail de votre question, mais les réponses fournies 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

45
Ross Allen

Voici une solution pure bash. Il lit les noms de fichier d'un fichier d'entrée (un par ligne) et les copie, 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 de 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 du 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;
7
terdon

Selon la description de la question, ma compréhension est la suivante:

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

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 en cours de traitement à utiliser dans la commande
  • --arg-file=input.txt spécifie de prendre des arguments pour commander à partir de input.txt
  • cp /path/to/Origin_dir/% /path/to/destination/ effectuera la commande cp en remplaçant le /path/to/Origin_dir/% par le /path/to/Origin_dir/ et en indiquant le nom du fichier en cours de traitement.

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
1