J'essaie donc de copier des fichiers dans un autre répertoire si leur nom de fichier commence par le même ID à 4 chiffres que les valeurs de ma liste. Je reçois soit les mauvaises données écrites dans le fichier, soit rien du tout.

Ce que j'ai jusqu'à présent:

import shutil
import os

ok_ids = [5252,
8396,
8397,
8397,
8556,
8004,
6545,
6541,
4392,
4392,
6548,
1363,
1363,
1363,
8489,
8652,
1368,
1368]

source = os.listdir("/Users/amm/Desktop/mypath1/")
destination = "/Users/amm/Desktop/mypath2/"

for files in source:
    for x in ok_ids:
        if files[:4] == x:
            shutil.copy(files,destination)
     else:
        print("not working")

Exemple de fichiers que j'essaie de copier, c'est-à-dire source

0000_051123_192805.txt
0000_051123_192805.txt
8642_060201_113220.txt
8652_060204_152839.txt
8652_060204_152839.txt
309-_060202_112353.txt
x104_051203_064013.txt

Le répertoire destination est vide

Quelques points importants: ok_ids ne contient pas de valeurs distinctes, mais j'aimerais que le programme traite la liste comme si elle contenait des valeurs distinctes. par exemple, 8397 apparaît deux fois dans la liste ok_ids et il n'est pas nécessaire de le répéter deux fois dans la boucle ok_ids (c'est une longue liste verrry et je n'ai pas envie d'éditer). source peut également contenir des identifiants en double, en utilisant l'exemple ci-dessus, ce sont 0000, 8652, mais le reste du nom de fichier est différent.

Donc en résumé ... si 0000 est dans ma liste ok_ids et qu'il y a des noms de fichiers commençant par 0000 dans mon répertoire source alors je veux les copier dans mon {{ Dossier X4}}.

J'ai regardé en utilisant .startswith mais ce n'est pas content d'utiliser une liste comme argument même si je la transforme en tuple puis en str. Toute aide serait incroyable.

MISE À JOUR

La raison pour laquelle cela ne fonctionne pas pourrait-elle être que certains des identifiants contiennent un trait d'union? et d'autres commencent par un caractère x pas une valeur int?

Les 4 premières valeurs sont l'ID, par exemple celles-ci sont toujours valides:

309-_060202_112353.txt
x104_051203_064013.txt
0
Abbie 16 avril 2018 à 06:07

4 réponses

Meilleure réponse
import os
import shutil
for root, dirs, files in os.walk("/Users/amm/Desktop/mypath1/"):
    for file in files:
        try:
            if int(file[:4]) in ok_ids:
               shutil.copy(file,destination)
        except:
            pass

Cela a fonctionné pour moi. Le seul hic, c'est qu'il explore tous les dossiers du même répertoire.

1
CoreCreatives 16 avril 2018 à 03:40

Cela devrait fonctionner:

for file in source:
    for x in set(ok_ids):
        if file.startswith(str(x)):
            shutil.copy(file, destination)

Utilisez set() pour rendre les nombres uniques et str() pour les convertir en chaîne. Vous pouvez donc prétraiter la liste dans un ensemble pour de meilleures performances.

Ou mieux encore, compte tenu de vos contraintes de dénomination:

if int(file.split("_")[0]) in ok_ids:

Pourquoi votre code ne fonctionne pas?

if files[:4] == x:

Vous comparez un str avec un int, qui, intuitivement, sera toujours faux.

4
iBug 16 avril 2018 à 03:18

files[:4] == x ne peut jamais être vrai car x est un entier et files[:4] est une chaîne. Peu importe si la représentation de x chaîne correspond:

>>> 123 == '123'
False

J'ai regardé en utilisant .startswith mais ce n'est pas content d'utiliser une liste comme argument même si je la transforme en tuple puis en str. Toute aide serait incroyable.

C'est sans doute la meilleure façon de résoudre le problème, mais vous n'avez pas seulement besoin d'un tuple - vous avez besoin des valeurs d'ID individuelles pour être des chaînes. Il n'y a pas de "cast" possible (ce ne sont pas vraiment des cast) que vous pouvez effectuer sur ok_ids qui affecte les éléments .

La façon la plus simple de le faire est de créer un tuple en premier lieu et de faire en sorte que les éléments du tuple soient des chaînes en premier lieu:

ok_ids = (
    '5252',
    '8396',
    # ...
    '1368'
)

Si vous ne contrôlez pas ces données, vous pouvez utiliser une expression de générateur passée à tuple pour créer le tuple:

ok_ids = tuple(str(x) for x in ok_ids)
0
Karl Knechtel 16 avril 2018 à 04:32

Votre code fonctionne pour moi avec la légère modification de str(x) au lieu de x.

Essayez d'utiliser ceci pour voir ce qu'il fait avec chaque fichier:

for files in source:
    for x in ok_ids:
        if files[:4] == str(x):
            print("File '{}' matched".format(files))
            break
    else:
        print("File '{}' not matched".format(files))

Ou bien, convertissez tous les éléments de ok_ids en chaînes et voyez ce que cela produit:

ok_ids = [str(id) for id in ok_ids]
files_matched = [file for file in source if file[:4] in ok_ids]
1
Bill 16 avril 2018 à 03:56