【PowerShell】サイズの大きいファイルを検索し、所有者情報と一緒にCSVに出力する

スポンサーリンク
powershell
スポンサーリンク

ファイルサイズの大きいものとその所有者が知りたい

「ファイルサーバーリソースマネージャー(FSRM)みたいに大きいファイルとその所有者をいっぺんに知りたいなぁ~」と思ったのでPowerShellでツールを作った。

搭載機能

  • 指定したフォルダ配下(サブフォルダ含む)のファイルに対して、ファイルサイズで対象を絞り、それぞれの所有者情報をCSVに出力する。
  • ユーザーはフォルダパス、ファイルサイズ(数値、単位、ファイルサイズ比較演算子)をGUIで指定できるようにする。
  • 一応指定サイズよりも大きいだけでなく小さい場合も条件づけできるようにする。
  • 取得する情報は以下とする。
     ファイルサイズ(KB)
     ファイルサイズ(MB)
     作成日時
     更新日時
     ファイル所有者
     ファイルパス
  • 結果はCSVファイルで出力する。ファイル名に実行年月日時分秒をつける。
  • 対象数が多いと時間がかかるので、進捗状況が表示されるようにする。
  • 後からエラーなどを終えるように実行ログを別ファイルとして吐き出す。

コード

絶対改善余地があるけどこんな感じ。

#
# ファイルサイズ指定してその所有者を特定するツール
#
# ファイル名:Search-FileOwner.ps1



# 調査対象フォルダの初期化
$SearchFolder = ""

# CSVテーブルの用意
$CSVdatas = @()

# 日付の取得
$date = Get-Date -Format "yyyyMMdd";

# 時間の取得
$time = Get-Date -Format "HHmmss";

# 調査結果を出力するフォルダ
$scriptPath = $MyInvocation.MyCommand.Path
$scriptPath_split = Split-Path -Parent $scriptPath
$ResultFolder = ($scriptPath_split+"\結果")

# 調査結果出力結果フォルダがなかったら作成
if( -not (Test-Path $ResultFolder) ) {
    New-Item $ResultFolder -Type Directory
}

# 調査結果出力ファイル名
$ResultFile = ( "\FileOwner_"+$date+"_"+$time+".csv" )
$ExecuteLogFile = ( "\ExecuteLog_"+$date+"_"+$time+".log" )

#調査結果出力フォルダとファイル名のマージ
$Result = Join-Path $ResultFolder $ResultFile
$ExecuteLog = Join-Path $ResultFolder $ExecuteLogFile

# アセンブリ読み込み
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# フォーム作成
$Form = New-Object System.Windows.Forms.Form 
$Form.Size = New-Object System.Drawing.Size(400,180) 
$Form.Text = "ファイル所有者調査ツール"

# ラベル作成(フォルダパス)
$LabelFilePath = New-Object System.Windows.Forms.Label
$LabelFilePath.Location = New-Object System.Drawing.Point(20,10)
$LabelFilePath.Size = New-Object System.Drawing.Size(300,20)
$LabelFilePath.Text = "ファイル調査対象フォルダのパスを入力してください"
$Form.Controls.Add($LabelFilePath)

# ラベル作成(ファイルサイズ選択)
$LabelFileSize = New-Object System.Windows.Forms.Label
$LabelFileSize.Location = New-Object System.Drawing.Point(20,60)
$LabelFileSize.Size = New-Object System.Drawing.Size(300,20)
$LabelFileSize.Text = "ファイルサイズ条件を入力/選択してください(数字)"
$Form.Controls.Add($LabelFileSize)

# フォルダ入力用テキストボックス
$TextBoxFilePath = New-Object System.Windows.Forms.TextBox
$TextBoxFilePath.Location = New-Object System.Drawing.Point(20,30)
$TextBoxFilePath.Size = New-Object System.Drawing.Size(300,20)
$Form.Controls.Add($TextBoxFilePath)

# ファイルサイズ(数字)入力用テキストボックス
$TextBoxFileSize = New-Object System.Windows.Forms.TextBox
$TextBoxFileSize.Location = New-Object System.Drawing.Point(20,80)
$TextBoxFileSize.Size = New-Object System.Drawing.Size(200,20)
$TextBoxFileSize.Text = "0"
$Form.Controls.Add($TextBoxFileSize)

# 参照ボタン
$ButtonFilePath = New-Object System.Windows.Forms.Button
$ButtonFilePath.Location = New-Object System.Drawing.Point(320,30)
$ButtonFilePath.Size = New-Object System.Drawing.Size(40,20)
$ButtonFilePath.Text = "参照"
$Form.Controls.Add($ButtonFilePath)

# OKボタン
$ButtonOK = New-Object System.Windows.Forms.Button
$ButtonOK.Location =  New-Object System.Drawing.Point(230,110)
$ButtonOK.Size = New-Object System.Drawing.Size(60,20)
$ButtonOK.Text = "OK"
$Form.Controls.Add($ButtonOK)

# Cancelボタン
$ButtonCancel = New-Object System.Windows.Forms.Button
$ButtonCancel.Location =  New-Object System.Drawing.Point(300,110)
$ButtonCancel.Size = New-Object System.Drawing.Size(60,20)
$ButtonCancel.Text = "キャンセル"
$ButtonCancel.DialogResult = "Cancel"
$Form.Controls.Add($ButtonCancel)

# ファイルサイズ単位選択用コンボボックスを作成
$Combo1 = New-Object System.Windows.Forms.Combobox
$Combo1.Location = New-Object System.Drawing.Point(220,80)
$Combo1.size = New-Object System.Drawing.Size(50,30)
$Combo1.DropDownStyle = "DropDownList"
$Combo1.FlatStyle = "standard"
$Combo1.font = $Font
$Combo1.BackColor = "#005050"
$Combo1.ForeColor = "white"

# ファイルサイズ条件選択用コンボボックスを作成
$Combo2 = New-Object System.Windows.Forms.Combobox
$Combo2.Location = New-Object System.Drawing.Point(270,80)
$Combo2.size = New-Object System.Drawing.Size(90,30)
$Combo2.DropDownStyle = "DropDownList"
$Combo2.FlatStyle = "standard"
$Combo2.font = $Font
$Combo2.BackColor = "#005050"
$Combo2.ForeColor = "white"

# ファイルサイズ単位選択用コンボボックスに項目を追加
[void] $Combo1.Items.Add("KB")
[void] $Combo1.Items.Add("MB")
[void] $Combo1.Items.Add("GB")
[void] $Combo1.Items.Add("TB")
[void] $Combo1.Items.Add("PB")

# ファイルサイズ条件選択用コンボボックスに項目を追加
[void] $Combo2.Items.Add("より大きい")
[void] $Combo2.Items.Add("以上")
[void] $Combo2.Items.Add("以下")
[void] $Combo2.Items.Add("より小さい")

# フォームにコンボボックスを追加
$form.Controls.Add($Combo1)
$form.Controls.Add($Combo2)

# フォームを最前面に表示
$form.Topmost = $True

# 参照ボタンをクリック時の動作
$ButtonFilePath.add_click{

    #ダイアログを表示しファイルを選択する
    $Dialog = New-Object System.Windows.Forms.FolderBrowserDialog
    if($Dialog.ShowDialog() -eq "OK"){
        $TextBoxFilePath.Text = $Dialog.SelectedPath
    }
}

# OKボタンをクリック時の動作
$ButtonOK.add_click{

    #ファイルパスが入力されていないときは背景を黄色にする
    if($TextBoxFilePath.text -eq ""){
        $TextBoxFilePath.BackColor = "yellow"
    }else{

        #ファイルサイズが半角数値で入力されていないときは背景を黄色にして注記する
        #ファイルサイズ比較条件が未記入の場合はプルダウンから選択するよう注記する
        if([int]::TryParse($TextBoxFileSize.text,[ref]$null)) {
             if($combo2.Text -eq ""){
                $TextBoxFileSize.BackColor = "yellow"
                $TextBoxFileSize.text = "プルダウンから値を選択してください"
             } else {
                        $Form.DialogResult = "OK"
                    }
 

            } else {
                        $TextBoxFileSize.BackColor = "yellow"
                        $TextBoxFileSize.text = "半角数字で入力してください"
                    }
        }
}


Start-Transcript $ExecuteLog


#フォームを表示し処理が完了したらファイルパスを返す
$FormResult = $Form.ShowDialog()
if($FormResult -eq "OK"){

    $SearchFolder = $TextBoxFilePath.text
    $FileSizeInt = $TextBoxFileSize.text
    $FileSizeUnit = $combo1.Text
    $FileSizeIU = [string]$FileSizeInt+[string]$FileSizeUnit

    echo $SearchFolder"を調査中…ファイルが多いと時間かかります。調査中にPowershellのウィンドウのサイズ変更をしないでください。"


###進捗表示用###
echo "ファイル数取得中"

###ファイルサイズ比較条件ごとにファイル取得文を変更###
if($combo2.Text -eq "より大きい"){
    $GetSearchFolder = Get-ChildItem -File -Recurse $SearchFolder | Where-Object { $_.Length -gt $FileSizeIU } 
    } else {
    if($combo2.Text -eq "以上"){
        $GetSearchFolder = Get-ChildItem -File -Recurse $SearchFolder | Where-Object { $_.Length -ge $FileSizeIU } 
        } else {
        if($combo2.Text -eq "以下"){
            $GetSearchFolder = Get-ChildItem -File -Recurse $SearchFolder | Where-Object { $_.Length -le $FileSizeIU } 
            } else {                           
                 $GetSearchFolder = Get-ChildItem -File -Recurse $SearchFolder | Where-Object { $_.Length -lt $FileSizeIU } 
            }
        }
    }
    
$fileCount = $GetSearchFolder.Length
$counter   = 0
echo ("ファイル数="+$fileCount)
echo "チェック開始"
echo ""
$denominator = "/"+[string]$fileCount

###CSVデータとしてファイル毎の要素(サイズや作成時間、更新時間、所有者、ファイルパス)を取得・格納する

ForEach($a in $GetSearchFolder) {
    $counter ++;
    Write-Progress -activity "進捗状況" -status $counter$denominator -percentComplete ($counter / $fileCount * 100)

    
        $CSVdata = New-Object PSObject | Select-Object FileSizeKB,FileSizeMB,CreationTime,LastWriteTime,Owner,Path
        $path = $a.FullName
        $Item = Get-Item $path
        $filesizeKB = [Math]::Round(($Item).length/1KB, 1, [MidpointRounding]::AwayFromZero);
        $filesizeMB = [Math]::Round(($Item).length/1MB, 1, [MidpointRounding]::AwayFromZero);
        $CRTime = ($Item).CreationTime
        $LWTime = ($Item).LastWriteTime
        $Ownter = (Get-Acl $path).Owner

        $CSVdata.FileSizeKB = $filesizeKB
        $CSVdata.FileSizeMB = $filesizeMB
        $CSVdata.CreationTime = $CRTime
        $CSVdata.LastWriteTime = $LWTime
        $CSVdata.Owner = $Ownter
        $CSVdata.Path =$path

        $CSVdatas += $CSVdata

} 

$CSVdatas | Sort-Object FileSizeKB -Descend | Export-CSV $Result -Encoding Default -NoTypeInformation

Invoke-item $Result

} else {
}
Stop-Transcript

実行イメージ

調査対象フォルダ、ファイルサイズ指定画面
結果画面

注意点と補足

  • PowerShellが実行可能な環境である必要があります。

改版履歴

2021/02/10 初版公開

コメント

タイトルとURLをコピーしました