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 .
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 │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
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
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 ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
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.
@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
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')
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(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)
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.
"""whileTrue:
copy_buffer = source.read(buffer_size)ifnot 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)
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')
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:
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.
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.
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[:]
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()où 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.
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)
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 importPath
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
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.
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).
Réponses:
shutil
propose de nombreuses méthodes. L'un d'eux est:Si vous utilisez des
os.path
opérations, utilisezcopy
plutôt quecopyfile
.copyfile
n'acceptera que des chaînes .la source
~
, mais il peut traiter les chemins relatifsla source
copy2(src,dst)
est souvent plus utile quecopyfile(src,dst)
parce que :dst
d'être un répertoire (au lieu du nom de fichier cible complet), auquel cas le nom de base desrc
est utilisé pour créer le nouveau fichier;Voici un petit exemple:
la source
copyfile
est considérablement plus rapide quecopy2
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?/new/dir
s'agit d'un répertoire existant, voir le commentaire de @ MatthewAlpert./new/dir/
n'existe pas, Python lancera unIsADirectoryError
, sinon il copie le fichier/new/dir/
sous le nom d'origine.Vous pouvez utiliser l'une des fonctions de copie du
shutil
package:Exemple:
la source
En Python, vous pouvez copier les fichiers en utilisant
shutil
moduleos
modulesubprocess
module1) Copie de fichiers à l'aide du
shutil
moduleshutil.copyfile
Signatureshutil.copy
Signatureshutil.copy2
Signatureshutil.copyfileobj
Signature2) Copie de fichiers à l'aide du
os
moduleos.popen
Signatureos.system
Signature3) Copie de fichiers à l'aide du
subprocess
modulesubprocess.call
Signaturesubprocess.check_output
Signaturela source
['copy', sourcefile, destfile]
syntaxe dans la mesure du possible, surtout si les paramètres proviennent de l'entrée utilisateur.os.popen
est obsolète depuis un moment maintenant. etcheck_output
ne renvoie pas l'état mais la sortie (qui est vide dans le cas decopy/cp
)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.
Si vous souhaitez copier par nom de fichier, vous pouvez faire quelque chose comme ceci:
la source
shutil.copyfileobj
. De plus, vous n'en avez pastry, 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 lesshutil.copyfile
wrapsshutil.copyfileobj
.dest
d'êtreopen(dest, 'wb')
Utilisez le module shutil .
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.
la source
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
la source
Tout d'abord, j'ai fait une feuille de calcul exhaustive des méthodes de shutil pour votre référence.
Deuxièmement, expliquez les méthodes de copie dans des exemples:
Copiez récursivement une arborescence de répertoires entière enracinée dans src, en retournant le répertoire de destination
la source
Pour les petits fichiers et en utilisant uniquement des modules intégrés python, vous pouvez utiliser la ligne unique suivante:
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.
la source
.read()
et.write()
sont tamponnés par défaut (au moins pour CPython).open()
IO soit mis en mémoire tampon par défaut ne vous aide pas ici, car ilread()
est spécifié comme suit: 'Si n est négatif ou omis, lisez jusqu'à EOF.' Cela signifie que leread()
retourne le contenu complet du fichier sous forme de chaîne.Vous pourriez utiliser
os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
ou comme je l'ai fait,
où
rawfile
est le nom que j'avais généré à l'intérieur du programme.Ceci est une solution Linux uniquement
la source
shutil
n'est pas disponible -subprocess.run()
(sansshell=True
!) Est la meilleure alternative àos.system()
.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, lesshutil
amis sont recommandés plutôt que d'appeler un programme externe.)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.
la source
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 avecoutput.write(read(n)); output.flush()
oùn
est 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.shutil
? Même en ignorantshutil
, 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.la source
call
n'est pas sûr. Veuillez vous référer au document sous-processus à ce sujet.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):
write_bytes
écrasera tout ce qui était à l'emplacement de la destinationla source
shutil
gère tous les cas spéciaux pour vous et vous donne la tranquillité d'esprit.Ouvrez le fichier source en mode lecture et écrivez dans le fichier de destination en mode écriture.
la source
.close()
sur tous cesopen(...)
s?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
La commande suivante est utilisée pour copier un fichier avec des informations de métadonnées
la source
copy
alors exécutercopystat
pour conserver les métadonnées du fichier. En Python 3.3+copystat
copie également les attributs étendus.