前回のおさらい
過去3回に渡って、osモジュールとshutilモジュールを比較するため、ファイル・フォルダ操作に関して解説をしています。
今回はとうとうshutilモジュールに関して解説を進めていきたいと思います。
まずはこれまでのおさらい。
これまでosモジュールを使って、フォルダの作成、フォルダ・ファイルの名前変更、移動、削除を行ってきました。
表にしてみるとこんな感じです。
osモジュール | |
フォルダの作成 | os.mkdir(“フォルダ名”) |
フォルダ名の変更 | os.rename(“変更前”, “変更後”) |
ファイル名の変更 | os.rename(“変更前”,”変更後”) |
フォルダの移動 | os.rename(“変更前”,”変更後”) |
ファイルの移動 | os.rename(“変更前”,”変更後”) |
フォルダの削除 | os.rmdir(“フォルダ名”) |
ファイルの削除 | os.rmove(“ファイル名”) |
今回もファイル・フォルダ操作を行いますので、とりあえず最初にこんな感じでファイル・フォルダ構造を整えておきます。
document1.txtには1から5の数字を書いておいてください。
document2.txtは特に何も書いていない空のファイルでOKです。
この状態でos_module_test内で新しいPythonプログラムを作成します。
そして今回はshutilモジュールをインポートしてください。
import shutil
これで準備は完了です。
ファイルのコピー:shutil.copyfile(“コピー元”,”コピー先”)
ファイル・フォルダのコピーは実はosモジュールではなかった機能です。
(私が知らないだけかもしれませんが…)
まずはフォルダのコピーを紹介します。
フォルダのコピーはshutil.copyfile(“コピー元”,”コピー先”)でできます。
document1.txtをdocument3.txtとしてコピーしてみましょう。
shutil.copyfile("document1.txt", "document3.txt")
document1.txtには1から5の数字が書かれているので、コピー先であるdocument3.txtにも1から5の数字が書かれているはずです。
確認してみましょう。
確かに1から5の数字が書かれていて、コピーされたファイルだと分かりました。
ちなみに同じフォルダに同じファイル名でコピーしようとするとどうなるでしょうか。
shutil.copyfile("document1.txt", "document1.txt")
実行結果
---------------------------------------------------------------------------
SameFileError Traceback (most recent call last)
<ipython-input-7-c2cfe34d6f53> in <module>
----> 1 shutil.copyfile("document1.txt", "document1.txt")
/opt/anaconda3/lib/python3.7/shutil.py in copyfile(src, dst, follow_symlinks)
102 """
103 if _samefile(src, dst):
--> 104 raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
105
106 for fn in [src, dst]:
SameFileError: 'document1.txt' and 'document1.txt' are the same file
同じファイルだということでコピーできないとエラーが出ました。
すでにあるファイル名をコピー先に指定してみる
ではすでにあるファイル名でコピーしようとするとどうなるでしょうか。
document3.txtを開いて中身を消した後、document1.txtをdocument3.txtとしてコピーしてみましょう。
shutil.copyfile("document1.txt", "document3.txt")
数字を消したはずなのに、1から5の数字が書かれています。
これはdocument1.txtがdocument3.txtに上書きされたということを示しています。
ということですでにあるファイル名をコピー先に指定すると上書きされます。
違うフォルダ間でコピー
コピー元、コピー先にはパスを含んだ形でもコピーできます。
document1.txtをfolder2の中にdocument1.txtとしてコピーしてみましょう。
shutil.copyfile("document1.txt", "./folder2/document1.txt")
前に解説した通り、folder2の前にある”./”は現在のファイルを示しています。
document1.txtがfolder2内にdocument1.txtとしてコピーされました。
フォルダをコピーしてみる
ファイルがコピーできるということで、フォルダはコピーできないのでしょうか。
folder1をfolder3としてコピーをしようとしてみます。
shutil.copyfile("folder1", "folder3")
実行結果
---------------------------------------------------------------------------
IsADirectoryError Traceback (most recent call last)
<ipython-input-9-bc8615ecadd5> in <module>
----> 1 shutil.copyfile("folder1", "folder3")
/opt/anaconda3/lib/python3.7/shutil.py in copyfile(src, dst, follow_symlinks)
118 os.symlink(os.readlink(src), dst)
119 else:
--> 120 with open(src, 'rb') as fsrc:
121 with open(dst, 'wb') as fdst:
122 copyfileobj(fsrc, fdst)
IsADirectoryError: [Errno 21] Is a directory: 'folder1'
folder1はフォルダ(directory:ディレクトリ)だということでエラーが出てきました。
実はフォルダをコピーするには違うコマンドが存在するのです。
フォルダをコピーする方法:shutil.copytree(“コピー元”, “コピー先”)
フォルダをコピーするには、shutil.copytree(“コピー元”,”コピー先”)というコマンドを使用します。
ということでfolder1をfolder3としてコピーしてみましょう。
shutil.copytree("folder1", "folder3")
コピーすることができました。
ここで一つ疑問です。
前にos.rmdirでフォルダを削除しようとした際、空のフォルダなら削除できたのですが、中に何かファイルなどが存在する場合は削除できませんでした。
このshutil.copytreeも同じ様な制限はあるのでしょうか。
中身があるフォルダをコピーしてみる
ということで中身が入っているfolder2をfolder4としてコピーしてみましょう。
shutil.copytree("folder2", "folder4")
実行した結果、folder4が作られ、その中にfolder2と同じ様にdocument1.txtとdocument2.txtがあります。
ということでshutil.copytreeでは中にファイルがあろうがなかろうがコピーすることができるということです。
違うフォルダにコピーしてみる
前回、ファイルをコピーする際、コピー元やコピー先にはパスを含んだ形でも指定可能だとお話ししました。
ということでフォルダでも同じこととが可能なのか試してみましょう。
今回は先ほどfolder2からコピーしたfolder4を、さらにfolder3の中にfolder4としてコピーしてみます。
shutil.copytree("folder4", "./folder3/folder4")
folder3の中にfolder4が作成され、その中にdocument1.txtとdocument2.txtが存在する形になりました。
ということでコピー元、コピー先にパスを含んだ形でもコピーすることができます。
すでに存在するフォルダ名をコピー先に指定してみる
ではちょっと指定を間違えたとして、コピー先をすでにあるフォルダ名にしてしまった場合どうなるでしょうか。
現在、フォルダはfolder1、folder2、folder3、folder4があります。
そこでfolder1をfolder4としてコピーしてみます。
shutil.copytree("folder1", "folder4")
実行結果
---------------------------------------------------------------------------
FileExistsError Traceback (most recent call last)
<ipython-input-8-cc5938e3cc6e> in <module>
----> 1 shutil.copytree("folder1", "folder4")
/opt/anaconda3/lib/python3.7/shutil.py in copytree(src, dst, symlinks, ignore, copy_function, ignore_dangling_symlinks)
322 ignored_names = set()
323
--> 324 os.makedirs(dst)
325 errors = []
326 for name in names:
/opt/anaconda3/lib/python3.7/os.py in makedirs(name, mode, exist_ok)
219 return
220 try:
--> 221 mkdir(name, mode)
222 except OSError:
223 # Cannot rely on checking for EEXIST, since the operating system
FileExistsError: [Errno 17] File exists: 'folder4'
ちょっと長いエラーが出てきてびっくりしましたが、要するにもうfolder4があるからコピーできないということです。
次回はshutilモジュールを使って、ファイルやフォルダを移動、名前を変更する方法を解説していきましょう。
ではでは今回はこんな感じで。
コメント