76176


Desktop上に、test_dir1というフォルダと、test_dir2というフォルダがあって  
これら2つのフォルダを、Pythonを使ってzip_testという1つのフォルダにzip圧縮して入れたいのですが、どうすれば良いですか？

shutilというライブラリを使ってやろうと思ったのですが、1つのフォルダしか圧縮する方法しか見つかりませんでした。

[code]

    import shutil
    shutil.make_archive('C:/Users/xxx/Desktop/zip_test', 'zip', root_dir='C:/Users/xxx/Desktop/test_dir1')
    
[/code]

フォルダを別途作成して、そのフォルダ内に2つのフォルダをコピーした後に圧縮したりするのが良いのでしょうか？  
もし、1つのコマンドで実行できる方法があるなら、知りたいです。


CC BY-SA 4.0
2021-05-29T05:58:03.653
76174
2021-05-29T09:19:00.543
36446
question
python
Pythonで複数フォルダを1つのZIPファイルに圧縮する方法


`shutil`だと, 二度実行すると zipが置き換えられるし, 一度に複数ディレクトリー指定というのもなさそうです。

とりあえずひとつ分のディレクトリーで `shutil`で作成し, もう一つ分のディレクトリーを `zipfile` で追加するとか, 最初からすべて
`zipfile`で行うかになるでしょう

以下は `zipfile`使ったコードです (Ubuntuにて動作)

[code]

    from zipfile import ZipFile,ZIP_DEFLATED
    from pathlib import Path
    
    desktop = Path.home()/ 'Desktop/'
    with ZipFile(desktop/'newzip.zip', 'w', compression=ZIP_DEFLATED) as zf:
        for f in desktop.glob('test_dir*/*'):
            if f.is_file():
                zf.write(f, arcname=f.relative_to(desktop))
    
[/code]

* * *

たぶん Desktop辺りでプラットフォームで異なることもあるかもだけど大抵はそのまま動くはず


CC BY-SA 4.0
2021-05-29T07:00:15.247
76175
2021-05-29T07:06:27.223
2021-05-29T07:06:27.223
43025
43025
76174
answer


[shutils.make_archive()
のソースコード](https://github.com/python/cpython/blob/3.8/Lib/shutil.py#L940)
を参考にすると(というよりコピペですが)、以下の様に書けます。

[code]

    import os
    from zipfile import ZipFile, ZIP_DEFLATED
    
    def make_zipfile_from_multiple_directory(zip_filename, src_dirs):
      save_cwd = os.getcwd()
      with ZipFile(zip_filename, 'w', compression=ZIP_DEFLATED) as zf:
        for base_dir in src_dirs:
          path_dir, path_base = os.path.split(os.path.realpath(base_dir))
          os.chdir(path_dir)
          zf.write(path_base, path_base)
          for dirpath, dirnames, filenames in os.walk(path_base):
            for name in sorted(dirnames):
              path = os.path.normpath(os.path.join(dirpath, name))
              zf.write(path, path)
            for name in filenames:
              path = os.path.normpath(os.path.join(dirpath, name))
              if os.path.isfile(path):
                zf.write(path, path)
    
      os.chdir(save_cwd)
    
    if __name__ == '__main__':
      root_dir = 'C:/Users/xxx/Desktop/'
      zip_filename = os.path.join(root_dir, 'zip_test.zip')
      src_dirs = [os.path.join(root_dir, d) for d in ('test_dir1', 'test_dir2')]
    
      make_zipfile_from_multiple_directory(zip_filename, src_dirs)
    
[/code]


CC BY-SA 4.0
2021-05-29T08:52:27.317
76176
2021-05-29T09:19:00.543
2021-05-29T09:19:00.543
76174
answer