Comment copier un fichier en Python?


2480

Comment copier un fichier en Python?

Je n'ai rien trouvé sous os.


117
Il semble que cp ne soit pas un appel système et n'appartienne donc pas au module os. Il s'agit d'une commande shell, elle est donc placée dans le module shutil.
waldol1

Réponses:


3015

shutilpropose de nombreuses méthodes. L'un d'eux est:

from shutil import copyfile
copyfile(src, dst)
  • Copiez le contenu du fichier nommé src dans un fichier nommé dst .
  • L'emplacement de destination doit être accessible en écriture; sinon, une exception IOError sera déclenchée .
  • Si dst existe déjà, il sera remplacé.
  • Les fichiers spéciaux tels que les périphériques et les canaux de caractères ou de blocs ne peuvent pas être copiés avec cette fonction.
  • Avec copy , src et dst sont des noms de chemin donnés sous forme de chaînes .

Si vous utilisez des os.pathopérations, utilisez copyplutôt que copyfile. copyfilen'acceptera que des chaînes .


147
Quelle est la différence entre copy et copyfile?
Matt

389
en copie (src, dst) le dst peut être un répertoire.
Owen

41
Notez que toutes les métadonnées ne seront pas copiées, selon votre plate-forme.
Kevin Horn

12
Notez qu'il ne s'agit pas d'une opération atomique. Prenez soin de l'utiliser dans une application filetée.
waterbyte

4
Notez qu'il ne peut pas gérer les abréviations comme ~, mais il peut traiter les chemins relatifs
zwep

1255
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│     Function     │ Copies │   Copies  │Can use│   Destination  │
│                  │metadata│permissions│buffer │may be directory│
├──────────────────┼────────┼───────────┼───────┼────────────────┤
│shutil.copy       │   No   │    Yes    │   No  │      Yes       │
│shutil.copyfile   │   No   │     No    │   No  │       No       │
│shutil.copy2      │  Yes   │    Yes    │   No  │      Yes       │
│shutil.copyfileobj│   No   │     No    │  Yes  │       No       │
└──────────────────┴────────┴───────────┴───────┴────────────────┘

733

copy2(src,dst)est souvent plus utile que copyfile(src,dst)parce que :

  • il permet dstd'être un répertoire (au lieu du nom de fichier cible complet), auquel cas le nom de base de srcest utilisé pour créer le nouveau fichier;
  • il conserve les informations de modification et d'accès d'origine (mtime et atime) dans les métadonnées du fichier (cependant, cela s'accompagne d'une légère surcharge).

Voici un petit exemple:

import shutil
shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext

19
J'essaie de copier aléatoirement des fichiers de 100k à partir d'un million de fichiers. copyfileest considérablement plus rapide quecopy2
Vijay

4
ai-je raison de supposer que shutil.copy2('/dir/file.ext', '/new/dir/')(avec une barre oblique après le chemin cible) supprimera l'ambiguïté sur l'opportunité de copier dans un nouveau fichier appelé "dir" ou de placer le fichier dans un répertoire de ce nom?
Zak

1
@Vijay Je pense que cette surcharge est due à la copie des métadonnées.
Jonathan H

@Zak Il n'y a aucune ambiguïté s'il /new/dirs'agit d'un répertoire existant, voir le commentaire de @ MatthewAlpert.
Jonathan H

@Zak Vous avez raison, l'ajout d'une barre oblique à la fin supprime l'ambiguïté. S'il /new/dir/n'existe pas, Python lancera un IsADirectoryError, sinon il copie le fichier /new/dir/sous le nom d'origine.
martonbognar

125

Vous pouvez utiliser l'une des fonctions de copie du shutilpackage:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
La fonction préserve les supports accepte les copies autres
                      répertoire des autorisations dest. fichier métadonnées obj  
―――――――――――――――――――――――――――――――――――――――――――――――――― ――――――――――――――――――――――――――――
shutil.copy               ✔ ✔ ☐ ☐
 shutil.copy2              ✔ ✔ ☐ ✔
 shutil.copyfile           ☐ ☐ ☐ ☐
 shutil.copyfileobj        ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Exemple:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')

10
Juste curieux, comment avez-vous généré ce tableau?
lightalchemist

16
@lightalchemist Je viens d'utiliser vim comme bloc-notes, j'ai copié les symboles unicode utilisés à partir d'une table wikipedia et j'ai copié le résultat dans l'éditeur stackoverflow pour le polissage final.
maxschlepzig

3
En quoi est-ce différent des autres réponses 2 ans plus tôt? stackoverflow.com/a/30359308/674039
wim

1
@wim, vous devez comparer ma réponse avec la version 2017 de la réponse que vous avez liée et qui était à jour lorsque j'ai posté ma réponse. Principales différences: ma réponse utilise des en-têtes de colonne meilleurs / plus descriptifs, la disposition du tableau n'est pas gênante, elle inclut des liens directs dans la documentation et j'ai ajouté une colonne (c'est-à-dire «accepte le fichier obj»).
maxschlepzig

4
D'ACCORD. YMMV, mais je pense que les changements cosmétiques et les améliorations mineures comme celle-ci sont mieux faits comme des modifications sur les réponses existantes, plutôt que la duplication des réponses.
wim

104

En Python, vous pouvez copier les fichiers en utilisant


import os
import shutil
import subprocess

1) Copie de fichiers à l'aide du shutilmodule

shutil.copyfile Signature

shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)

# example    
shutil.copyfile('source.txt', 'destination.txt')

shutil.copy Signature

shutil.copy(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy('source.txt', 'destination.txt')

shutil.copy2 Signature

shutil.copy2(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy2('source.txt', 'destination.txt')  

shutil.copyfileobj Signature

shutil.copyfileobj(src_file_object, dest_file_object[, length])

# example
file_src = 'source.txt'  
f_src = open(file_src, 'rb')

file_dest = 'destination.txt'  
f_dest = open(file_dest, 'wb')

shutil.copyfileobj(f_src, f_dest)  

2) Copie de fichiers à l'aide du osmodule

os.popen Signature

os.popen(cmd[, mode[, bufsize]])

# example
# In Unix/Linux
os.popen('cp source.txt destination.txt') 

# In Windows
os.popen('copy source.txt destination.txt')

os.system Signature

os.system(command)


# In Linux/Unix
os.system('cp source.txt destination.txt')  

# In Windows
os.system('copy source.txt destination.txt')

3) Copie de fichiers à l'aide du subprocessmodule

subprocess.call Signature

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.call('cp source.txt destination.txt', shell=True) 

# In Windows
status = subprocess.call('copy source.txt destination.txt', shell=True)

subprocess.check_output Signature

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.check_output('cp source.txt destination.txt', shell=True)

# In Windows
status = subprocess.check_output('copy source.txt destination.txt', shell=True)


9
L'utilisation de commandes à chaîne unique est un mauvais style de codage (flexibilité, fiabilité et sécurité), utilisez plutôt la ['copy', sourcefile, destfile]syntaxe dans la mesure du possible, surtout si les paramètres proviennent de l'entrée utilisateur.
Marcel Waldvogel

8
Pourquoi citez-vous autant de mauvaises alternatives aux fonctions de copie shutil?
maxschlepzig

6
shutil est intégré, pas besoin de proposer des alternatives non portables. La réponse pourrait en fait être améliorée en supprimant les solutions dépendantes du système, et après cette suppression, cette réponse n'est qu'une copie des réponses existantes / une copie de la documentation.
Jean-François Fabre

3
os.popenest obsolète depuis un moment maintenant. et check_outputne renvoie pas l'état mais la sortie (qui est vide dans le cas de copy/cp)
Jean-François Fabre

2
shutil ne copie pas réellement les fichiers. Il y a un gros gros avertissement en haut des documents . "cela signifie que le propriétaire et le groupe de fichiers sont perdus ainsi que les listes de contrôle d'accès. Sous Mac OS, la fourchette de ressources et les autres métadonnées ne sont pas utilisées. Cela signifie que les ressources seront perdues et que le type de fichier et les codes de créateur ne seront pas corrects. Sous Windows, les propriétaires de fichiers, les listes de contrôle d'accès et les autres flux de données ne sont pas copiés. "
gman

96

La copie d'un fichier est une opération relativement simple, comme le montrent les exemples ci-dessous, mais vous devez plutôt utiliser le module shutil stdlib pour cela.

def copyfileobj_example(source, dest, buffer_size=1024*1024):
    """      
    Copy a file from source to dest. source and dest
    must be file-like objects, i.e. any object with a read or
    write method, like for example StringIO.
    """
    while True:
        copy_buffer = source.read(buffer_size)
        if not copy_buffer:
            break
        dest.write(copy_buffer)

Si vous souhaitez copier par nom de fichier, vous pouvez faire quelque chose comme ceci:

def copyfile_example(source, dest):
    # Beware, this example does not handle any edge cases!
    with open(source, 'rb') as src, open(dest, 'wb') as dst:
        copyfileobj_example(src, dst)

25
J'ai remarqué il y a un moment que le module est appelé shutil (singulier) et non shutils ( au pluriel), et en effet il est en Python 2.3. Néanmoins, je laisse cette fonction ici à titre d'exemple.
pi.

4
La copie du contenu d' un fichier est une opération simple. La copie du fichier avec ses métadonnées est tout sauf simple, d'autant plus si vous voulez être multi-plateforme.
LaC

3
Vrai. En regardant les documents shutil, la fonction copyfile ne copiera pas non plus les métadonnées.
pi.

3
Oui, je ne sais pas pourquoi vous ne copieriez pas simplement la source de shutil.copyfileobj. De plus, vous n'en avez pas try, finallyà gérer la fermeture des fichiers après des exceptions. Je dirais cependant que votre fonction ne devrait pas du tout être responsable de l'ouverture et de la fermeture des fichiers. Cela devrait aller dans une fonction wrapper, comme la façon dont les shutil.copyfilewraps shutil.copyfileobj.
ErlVolton

2
Le code ci-dessus doit spécifier destd'être open(dest, 'wb')
accessible en

69

Utilisez le module shutil .

copyfile(src, dst)

Copiez le contenu du fichier nommé src dans un fichier nommé dst. L'emplacement de destination doit être accessible en écriture; sinon, une exception IOError sera déclenchée. Si dst existe déjà, il sera remplacé. Les fichiers spéciaux tels que les périphériques et les canaux de caractères ou de blocs ne peuvent pas être copiés avec cette fonction. src et dst sont des noms de chemin donnés sous forme de chaînes.

Jetez un œil à filesys pour toutes les fonctions de gestion de fichiers et de répertoires disponibles dans les modules Python standard.


shutil ne copie pas réellement les fichiers. Il y a un gros gros avertissement en haut des documents . "cela signifie que le propriétaire et le groupe de fichiers sont perdus ainsi que les listes de contrôle d'accès. Sous Mac OS, la fourchette de ressources et les autres métadonnées ne sont pas utilisées. Cela signifie que les ressources seront perdues et que le type de fichier et les codes de créateur ne seront pas corrects. Sous Windows, les propriétaires de fichiers, les listes de contrôle d'accès et les autres flux de données ne sont pas copiés. "
gman

47

Exemple de copie de répertoire et de fichier - De Tim Golden's Python Stuff:

http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

import os
import shutil
import tempfile

filename1 = tempfile.mktemp (".txt")
open (filename1, "w").close ()
filename2 = filename1 + ".copy"
print filename1, "=>", filename2

shutil.copy (filename1, filename2)

if os.path.isfile (filename2): print "Success"

dirname1 = tempfile.mktemp (".dir")
os.mkdir (dirname1)
dirname2 = dirname1 + ".copy"
print dirname1, "=>", dirname2

shutil.copytree (dirname1, dirname2)

if os.path.isdir (dirname2): print "Success"

24

Tout d'abord, j'ai fait une feuille de calcul exhaustive des méthodes de shutil pour votre référence.

shutil_methods =
{'copy':['shutil.copyfileobj',
          'shutil.copyfile',
          'shutil.copymode',
          'shutil.copystat',
          'shutil.copy',
          'shutil.copy2',
          'shutil.copytree',],
 'move':['shutil.rmtree',
         'shutil.move',],
 'exception': ['exception shutil.SameFileError',
                 'exception shutil.Error'],
 'others':['shutil.disk_usage',
             'shutil.chown',
             'shutil.which',
             'shutil.ignore_patterns',]
}

Deuxièmement, expliquez les méthodes de copie dans des exemples:

  1. shutil.copyfileobj(fsrc, fdst[, length]) manipuler des objets ouverts
In [3]: src = '~/Documents/Head+First+SQL.pdf'
In [4]: dst = '~/desktop'
In [5]: shutil.copyfileobj(src, dst)
AttributeError: 'str' object has no attribute 'read'
#copy the file object
In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
    ...:      shutil.copyfileobj(f1, f2)
In [8]: os.stat(os.path.join(dst,'test.pdf'))
Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
  1. shutil.copyfile(src, dst, *, follow_symlinks=True) Copier et renommer
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
  1. shutil.copy() Copiez sans prédéfinir les métadonnées
In [10]: shutil.copy(src, dst)
Out[10]: ~/desktop/Head+First+SQL.pdf'
#check their metadata
In [25]: os.stat(src)
Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
# st_atime,st_mtime,st_ctime changed
  1. shutil.copy2() Copier en conservant les métadonnées
In [30]: shutil.copy2(src, dst)
Out[30]: ~/desktop/Head+First+SQL.pdf'
In [31]: os.stat(src)
Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
# Preseved st_mtime
  1. shutil.copytree()

Copiez récursivement une arborescence de répertoires entière enracinée dans src, en retournant le répertoire de destination


1
shutil ne copie pas réellement les fichiers. Il y a un gros gros avertissement en haut des documents . "cela signifie que le propriétaire et le groupe de fichiers sont perdus ainsi que les listes de contrôle d'accès. Sous Mac OS, la fourchette de ressources et les autres métadonnées ne sont pas utilisées. Cela signifie que les ressources seront perdues et que le type de fichier et les codes de créateur ne seront pas corrects. Sous Windows, les propriétaires de fichiers, les listes de contrôle d'accès et les autres flux de données ne sont pas copiés. "
gman

19

Pour les petits fichiers et en utilisant uniquement des modules intégrés python, vous pouvez utiliser la ligne unique suivante:

with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())

Comme @maxschlepzig l'a mentionné dans les commentaires ci-dessous, ce n'est pas le moyen optimal pour les applications où le fichier est trop volumineux ou lorsque la mémoire est critique, donc la réponse de Swati devrait être préférée.


3
Ceci lit le fichier source complet en mémoire avant de le réécrire. Ainsi, cela gaspille inutilement de la mémoire pour toutes les opérations de copie de fichiers sauf les plus petites.
maxschlepzig

1
Est-ce vrai? Je pense .read()et .write()sont tamponnés par défaut (au moins pour CPython).
bande sonore

@soundstripe, bien sûr, cela est vrai. Le fait que l'objet fichier renvoyé par open()IO soit mis en mémoire tampon par défaut ne vous aide pas ici, car il read()est spécifié comme suit: 'Si n est négatif ou omis, lisez jusqu'à EOF.' Cela signifie que le read()retourne le contenu complet du fichier sous forme de chaîne.
maxschlepzig du

@maxschlepzig J'ai compris votre point et j'avoue que je n'en étais pas conscient. La raison pour laquelle j'ai fourni cette réponse était au cas où quelqu'un voudrait faire une simple copie de fichier en utilisant uniquement des intégrés, sans avoir besoin d'importer un module pour cela. Bien sûr, l'optimisation de la mémoire ne devrait pas être un problème si vous souhaitez cette option. Quoi qu'il en soit, merci d'avoir effacé cela. J'ai mis à jour la réponse en conséquence.
yellow01

14

Vous pourriez utiliser os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

ou comme je l'ai fait,

os.system('cp '+ rawfile + ' rawdata.dat')

rawfileest le nom que j'avais généré à l'intérieur du programme.

Ceci est une solution Linux uniquement


10
ce n'est pas portable et inutile car vous pouvez simplement utiliser shutil.
Corey Goldberg

4
Même lorsqu'il shutiln'est pas disponible - subprocess.run() (sans shell=True!) Est la meilleure alternative à os.system().
maxschlepzig

1
shutil est plus portable
Hiadore

1
subprocess.run()comme suggéré par @maxschlepzig est un grand pas en avant lors de l'appel de programmes externes. Cependant, pour plus de flexibilité et de sécurité, utilisez la ['cp', rawfile, 'rawdata.dat']forme de passage de la ligne de commande. (Cependant, pour la copie, les shutilamis sont recommandés plutôt que d'appeler un programme externe.)
Marcel Waldvogel

2
essayez cela avec des noms de fichiers contenant des espaces.
Jean-François Fabre

11

Pour les gros fichiers, j'ai lu le fichier ligne par ligne et lu chaque ligne dans un tableau. Ensuite, une fois que le tableau a atteint une certaine taille, ajoutez-le à un nouveau fichier.

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]

2
cela semble un peu redondant puisque l'auteur doit gérer la mise en mémoire tampon. for l in open('file.txt','r'): output.write(l)devrait travailler trouver; il suffit de configurer le tampon de flux de sortie selon vos besoins. ou vous pouvez passer par les octets en faisant une boucle sur un essai avec output.write(read(n)); output.flush()nest le nombre d'octets que vous souhaitez écrire à la fois. les deux n'ont pas non plus de condition pour vérifier ce qui est un bonus.
possède le

1
Oui, mais j'ai pensé que cela pourrait être plus facile à comprendre car il copie des lignes entières plutôt que des parties d'entre elles (au cas où nous ne saurions pas combien d'octets chaque ligne est).
ytpillai

Très vrai. Le codage pour l'enseignement et le codage pour l'efficacité sont très différents.
propriétaire du

1
en regardant la source - les appels écrits écrivent, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c . De plus, le flux de fichiers est déjà ouvert, donc l'écriture n'a pas besoin de le rouvrir à chaque fois.
possède

2
C'est affreux. Il fait un travail inutile sans raison valable. Cela ne fonctionne pas pour les fichiers arbitraires. La copie n'est pas identique à l'octet si l'entrée a des fins de ligne inhabituelles sur des systèmes comme Windows. Pourquoi pensez-vous que cela pourrait être plus facile à comprendre qu'un appel à une fonction de copie dans shutil? Même en ignorant shutil, une simple boucle de lecture / écriture de bloc (utilisant des E / S sans tampon) est simple, serait efficace et aurait beaucoup plus de sens que cela, et est donc sûrement plus facile à enseigner et à comprendre.
maxschlepzig

11
from subprocess import call
call("cp -p <file> <file>", shell=True)

10
Cela dépend de la plate-forme, donc je ne l'utiliserais pas.
Kevin Meier

5
Un tel calln'est pas sûr. Veuillez vous référer au document sous-processus à ce sujet.
buhtz

2
ce n'est pas portable et inutile car vous pouvez simplement utiliser shutil.
Corey Goldberg

2
Hmm pourquoi Python, alors?
Baris Demiray

Peut-être détecter le système d'exploitation avant de démarrer (que ce soit DOS ou Unix, car ce sont les deux plus utilisés)
MilkyWay90

8

Depuis Python 3.5, vous pouvez effectuer les opérations suivantes pour les petits fichiers (c'est-à-dire: les fichiers texte, les petits fichiers JPEG):

from pathlib import Path

source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())

write_bytes écrasera tout ce qui était à l'emplacement de la destination


2
Et puis quelqu'un utilise le code (accidentellement ou délibérément) sur un gros fichier… L'utilisation des fonctions de shutilgère tous les cas spéciaux pour vous et vous donne la tranquillité d'esprit.
Marcel Waldvogel

4
au moins, il ne répète pas les mêmes solutions encore et encore.
Jean-François Fabre

6
open(destination, 'wb').write(open(source, 'rb').read())

Ouvrez le fichier source en mode lecture et écrivez dans le fichier de destination en mode écriture.


1
L'idée est bonne et le code est beau, mais une fonction copy () appropriée peut faire plus de choses, comme copier des attributs (+ x bit), ou par exemple supprimer les octets déjà copiés au cas où une condition de disque plein serait trouvée .
Raúl Salinas-Monteagudo

1
Toutes les réponses doivent être expliquées, même s'il s'agit d'une seule phrase. Aucune explication ne crée un mauvais précédent et n'est pas utile pour comprendre le programme. Et si un noob Python complet arrivait et voyait cela, voulait l'utiliser, mais ne pouvait pas parce qu'il ne le comprenait pas? Vous voulez être utile à tous dans vos réponses.
connectyourcharger

1
N'est-ce pas manquer le .close()sur tous ces open(...)s?
luckydonald

Pas besoin de .close (), car nous ne stockons PAS l'objet pointeur de fichier n'importe où (ni pour le fichier src ni pour le fichier de destination).
S471

1
Même approche de perte de mémoire sous-optimale que la réponse de yellow01 .
maxschlepzig

-3

Python fournit des fonctions intégrées pour copier facilement des fichiers à l'aide des utilitaires du système d'exploitation.

La commande suivante est utilisée pour copier le fichier

shutil.copy(src,dst)

La commande suivante est utilisée pour copier un fichier avec des informations de métadonnées

shutil.copystat(src,dst)

Vous devez copyalors exécuter copystatpour conserver les métadonnées du fichier. En Python 3.3+ copystatcopie également les attributs étendus.
ingyhere
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.