LoginSignup
HOKKAPOKKA
@HOKKAPOKKA (HOKKA POKKA)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

ネストされてzipに格納されているファイルを集めて1つのフォルダに集約したい。(Windows10)

解決したいこと

ネストされてzipに格納されているファイルを集めて1つのフォルダに集約したい。(Windows10)

質問:
1つのzipファイルをWindows10の基本機能かオープンソースの信用できるツールを使ってバッチで解凍して、1つのフォルダ内に並列に格納したいのですが、要件が少し複雑です。

c:\XYZ.zipファイルを解凍した場合、決まって以下のような構造であることがわかっています。(下記のようにネストされています)
これを解凍して、すべてのファイル(*.xlsx)をc:\workフォルダの直下にすべて集めたいのです。
解凍したときの"XYZ"のフォルダ名は固定ですが、それ以下のフォルダ名やファイル名はすべて可変。
つまり、解凍してみないと末端のフォルダに何と言う名前のファイルが入っているかはわかりませんが、ファイルの階層数(この例では2階層)は一定です。
せっかく解凍してみても、フォルダはあっても末端にファイルが何も入っていない場合もあれば、複数入っている場合もあります。(ただし末端のファイル名が重複することはないことはわかっています)

しょうがなく普段は対話型でエクスプローラで開いて手動でコピーしているのですが、バッチファイルを工夫すればpkunzipとかでできそうな気がしてお知恵を拝借しています。

XYZ
└ABC
  └A
   └File-A.xlsx
  └B

   └File-B.xlsx
  └C

   └File-C.xlsx
└DEF
  └D

   └File-D.xlsx
  └E

   └File-E.xlsx
  └F

   └File-F.xlsx
└GHI
  └G

   └File-G.xlsx
  └H

   └File-H.xlsx
  └ I

   └File-I.xlsx

※言葉で書くと以下のようになります。念のため。
XYZフォルダの下に、ABCフォルダ, DEFフォルダ, GHIフォルダがあります。
ABCフォルダのさらに下に、Aフォルダ、Bフォルダ, Cフォルダがあります。
DEFフォルダのさらに下に、Dフォルダ、Eフォルダ, Fフォルダがあります。
GHIフォルダのさらに下に、Gフォルダ、Hフォルダ, Iフォルダがあります。
Aフォルダの下に、File-A.xlsxがあります。
Bフォルダの下に、File-B.xlsxがあります。
Cフォルダの下に、File-C.xlsxがあります。
Dフォルダの下に、File-D.xlsxがあります。
Eフォルダの下に、File-E.xlsxがあります。
Fフォルダの下に、File-F.xlsxがあります。
Gフォルダの下に、File-G.xlsxがあります。
Hフォルダの下に、File-H.xlsxがあります。
Iフォルダの下に、File-I.xlsxがあります。

0

2Answer

open System.IO
open System.IO.Compression

let extract zipPath destination =
    use archive = ZipFile.OpenRead(zipPath)

    archive.Entries
    |> Seq.where (fun e -> not (e.FullName.EndsWith("/")))
    |> Seq.iter (fun e -> e.ExtractToFile(Path.Combine(destination, e.Name)))
0

Comments

  1. @HOKKAPOKKA

    Questioner

    すいません、バッチファイルを使うと思いきや、知らない言語が来たのですが、これはどうやって使うのでしょうか。Link先は.net のように見えますが。

  2. PowerShellにしました。

    extract.ps1
    param (
        [string]$zipPath,
        [string]$destination
    )
    
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    
    $archive = [System.IO.Compression.ZipFile]::OpenRead($zipPath)
    
    $archive.Entries |
        Where-Object { -not $_.FullName.EndsWith("/") } |
        ForEach-Object {
            $path = [System.IO.Path]::Combine($destination, $_.Name)
            [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $path, $true)
        }
    $archive.Dispose()
    

    使用方法

    .\extract.ps1 -zipPath "C:\path\to\your\file.zip" -destination "C:\path\to\extract\to"
    

ネストされてzipに格納されているファイルを集めて1つのフォルダに集約したい。

すべてのファイル(*.xlsx)をc:\workフォルダの直下にすべて集めたいのです。

zipの中にさらに別なzipがあるわけではなく、フィルダ階層になっているzipファイルを解凍して、
フィルダ階層の末端にあるxlsxファイルを1箇所に集めれば良いということですね。

以下でどうでしょう。(テストしていません) テストしました。

バッチファイル
mkdir C:\XYZ 
mkdir C:\work 

tar -xf C:\XYZ.zip -C C:\XYZ 

FOR /R C:\XYZ %%X IN (*.xlsx) DO (
	copy %%X C:\work
)
0

Comments

  1. @HOKKAPOKKA

    Questioner

    これから実験してみます。なんだかシンプルで驚きました。
    そもそもWindowsでtarが使えることを初めて知りました。
    結果をご報告します。
    @nak435 さんはこちらの要件を完全に把握いただいているのでうれしい限りです!

  2. @HOKKAPOKKA

    Questioner

    やってみました!
    tarは期待通りに動いたのですが、*.xlsxをすべてc:\workにコピーするときに変な現象が起きました。
    copy C:\XYZ\2階層目\3階層目\4階層目\B123_報告書_24年05月 (2).xlsx C:\work
    が実行されたときに、確かにそこにB123_報告書_24年05月 (2).xlsx は存在するにもかかわらず、「指定されたファイルが見つかりません。」というメッセージとともにその部分はコピーされずに次へ行ってしまいます。
    見てみると、このように (2)とか (3)が入っているものだけはじかれています。
    バッチ起動の際に、文字コードか何かを指定すると改善されるのでしょうか?
    質問が本来の質問とかわってしまいましたが、困っています。

  3. @HOKKAPOKKA

    Questioner

    すいません。自己レスになりますが、ファイル名を"でくくるとできました。
    最後の部分が copy "%%X" C:\work です。
    これでコピーコマンドが発行されたものがすべてコピーされました。
    ところが、数が合わないんです。このバッチでやると77個の.xlsxファイルがc:\workにコピーされるんですが、解凍された親フォルダをdir /s *.xlx で見ると、ファイルが105個あるんです。よく見たら105個中28個が別階層のファイル名と重複していました。
    これは自己責任ですね。
    ということで、本当にこれでやりたいことなのですが、ここからはバッチの書き方の質問になるので、別の質問スレッドをこのあと入れます。
    ひとまず、お世話になりました。
    @Variablobさん、@nak435さん、感謝です。

  4. 最後の部分が copy "%%X" C:\workです。

    空白を含むパス名の考慮が漏れていました。
    クオーテーションマークで囲むことで正解です。

Your answer might help someone💌