ファイルサーバの容量ってすぐ無くなりますよね。
いくらでもお金を掛けられれば良いのですが、現実はそうでない。
容量確保のためにフォルダごとに圧縮したくなり作成しました。
やること
・指定ディレクトリ下のフォルダを列挙する
・7zipに圧縮する
・フォルダごとに実行する
これを2つの方法でやってみたいと思います。
・その1_Windows環境でコマンドラインオプションで。
・その2_Py7zrで。
どちらも前提として「7zip」が必要があります。
公式ウェブサイトからインストールしておきましょう!
その1はWindows環境のみですが、別のモジュールをインストール不要です。
その2はPythonがインストールされていれば、WindowsやLinux、Macなど、Pythonがサポートする多くのオペレーティングシステムで使える方法です。
どちらのやり方でも、複数ファイル、複数フォルダをまとめて圧縮できるので、手間が掛かりません。
それでは順番に見ていきましょう!
その1_Windows環境でコマンドラインオプションで
指定ディレクトリ下のフォルダを列挙する
指定ディレクトリ下のフォルダを列挙します。
今回は、実行ファイルと同じ階層の「target」以下のフォルダを対象にします。
「folder1」と「folder2」ですね。最終的にこれらがそれぞれ.7z形式の圧縮ファイルになればOKです。
まずはフォルダを列挙します。
import os
path_dir = "./target"# 圧縮するディレクトリのパス
folder_list = []
file_list = os.listdir(path_dir)
for file_name in file_list:
if os.path.isdir(os.path.join(path_dir, file_name)):
folder_list.append(file_name)
上記では、いったんディレクトリ下にあるものすべてでリストを作成します。
その中からフォルダのみを選んでフォルダリストにしています。
7zipに圧縮する
話は変わって、圧縮についてです。
7-zipはコマンドラインで圧縮ができます。(なので今回はPythonですが、バッチファイルだけでも記述できるそうです。)
import subprocess
path_exe = r'C:\Program Files\7-Zip\7z.exe'# 7zip実行ファイルのパス
result = subprocess.run(args)
Pythonから実行ファイルを呼び出すにはsubprocessを使います。
引数で圧縮対象などを指定します。上記は引数部分(args)を指定していないので動きませんが、骨子だけ抜き出すとこういう感じです。
引数部分も指定すると次です。
import subprocess
path_exe = r'C:\Program Files\7-Zip\7z.exe'# 7zip実行ファイルのパス
path_dir = "./target"# 圧縮するディレクトリのパス
item_path = os.path.join(path_dir, item)
comp_name = f"{item}.7z"
#絶対パスで出力先込みで指定
comp_name = os.path.abspath(os.path.join(path_dir, comp_name))
args = (
path_exe,
'a',
comp_name, # 圧縮後のファイル
item_path, # 圧縮対象フォルダ
)
result = subprocess.run(args)
圧縮後のファイルを、指定ディレクトリ下に置きたかったので、絶対パス指定で圧縮後のファイル名を設定しました。
フォルダごとに実行する
フォルダごとに実行するのはよくある処理ですね。
先ほど作ったフォルダリストを利用します。
for item in folder_list:
result = subprocess.run(args)
例によって、引数が入っていないですが、イメージは上記のとおりです。
サンプルコードその1
これらを合体したものがこちらです。
import os
import subprocess
path_exe = r'C:\Program Files\7-Zip\7z.exe'# 7zip実行ファイルのパス
path_dir = "./target"# 圧縮するディレクトリのパス
# ディレクトリ内のフォルダを格納するリストを初期化
folder_list = []
# ディレクトリ内のファイルとフォルダをリストアップ
file_list = os.listdir(path_dir)
# フォルダのみを抽出してリストに格納
for file_name in file_list:
if os.path.isdir(os.path.join(path_dir, file_name)):
folder_list.append(file_name)
# リストごとに実行
for item in folder_list:
item_path = os.path.join(path_dir, item)
comp_name = f"{item}.7z"
#絶対パスで出力先込みで指定
comp_name = os.path.abspath(os.path.join(path_dir, comp_name))
args = (
path_exe,
'a',
comp_name, # 圧縮後のファイル
item_path, # 圧縮対象フォルダ
)
print(f"圧縮対象:{path_dir}/{item}")
result = subprocess.run(args)
print(result)
実行結果がこちらです。
無事「folder1.7z」、「folder2.7z」に圧縮することができました。
おまけ_7zipコマンドラインオプション引数のご参考
どんな引数を設定すればよいかは、実行ファイルだけで実行するとヘルプを見ることができます。
例えば次を実行します。
import subprocess
result = subprocess.run(path_exe)
いくつかピックアップしたものが次です。
応用すれば、圧縮率の変更や、パスワード設定もできます。
Usage: 7z […] […] [@listfile]
a : Add files to archive
— : Stop switches and @listfile parsing
-m{Parameters} : set compression Method
-mmt[N] : set number of CPU threads
-mx[N] : set compression level: -mx1 (fastest) … -mx9 (ultra)
-o{Directory} : set Output directory
-p{Password} : set Password
その2_Py7zrで
subprocessを使う方法も便利ですが、環境に依存します。
例えば、WindowsでもLinuxでも使いたい場合に共通して動作しないことがあります。
そこで、別の方法として、「Py7zr」を使う方法をご紹介します。
Py7zrをインストールする
まずは何はともあれモジュールのインストールからです。
pip install py7zr
7zipに圧縮する
基本的な使用例です。
対象ファイル(フォルダ)を開き、圧縮後のファイル名を指定してアーカイブとして書き込みます。
import py7zr
# 使用例
def compress_to_7zip(source_file, destination_file):
with py7zr.SevenZipFile(destination_file, 'w') as archive:
archive.writeall(source_file)item_path = 'example.txt' # 圧縮する元のファイル
item_path = 'example.txt' # 圧縮する元のファイル
comp_name = 'compressed.7z' # 圧縮後のファイル名
compress_to_7zip(item_path, comp_name)
基本的な使い方はその1と大きく変わりません。
また、その他の要素(フォルダの列挙など)はその1と同じです。
ということでサンプルコードを見てみましょう。
その2_サンプルコード
その1のサンプルコードとほぼ同様です。
最後の「compress_to_7zip(item_path, comp_name)」だけ置き換えた格好です。
関数にしているので、こちらの方がスッキリしました。
import py7zr
import os
def compress_to_7zip(source_file, destination_file):
with py7zr.SevenZipFile(destination_file, 'w') as archive:
archive.writeall(source_file)
path_dir = "./target"# 圧縮するディレクトリのパス
# ディレクトリ内のフォルダを格納するリストを初期化
folder_list = []
# ディレクトリ内のファイルとフォルダをリストアップ
file_list = os.listdir(path_dir)
print(file_list)
# フォルダのみを抽出してリストに格納
for file_name in file_list:
if os.path.isdir(os.path.join(path_dir, file_name)):
folder_list.append(file_name)
# リストごとに実行
for item in folder_list:
item_path = os.path.join(path_dir, item)
comp_name = f"{item}.7z"
comp_name = os.path.abspath(os.path.join(path_dir, comp_name))
compress_to_7zip(item_path, comp_name)
実行結果は同様ですので割愛します。
おまけ_py7zrでパスワード設定する方法
最後にpy7zrでパスワード設定する方法をご紹介します。
引数を追加するだけです。
import py7zr
def compress_to_7zip_with_password(source_file, destination_file, encryption):
with py7zr.SevenZipFile(destination_file, 'w', password=encryption) as archive:
archive.writeall(source_file)
今回は7zipでフォルダごとに圧縮する方法を2通りご紹介しました。
いかがでしたでしょうか。
大量に圧縮対象がある場合でも、この方法なら手間が掛かりません。
今回は以上になります。
少しでもお役に立てれば幸いです。
それでは、読んで頂きありがとうございました!