解決済み

フォルダサイズの大きい順に並べ替えについて

  • 困ってます
  • 質問No.9586201
  • 閲覧数172
  • ありがとう数10
  • 気になる数0
  • 回答数4
  • コメント数0

お礼率 72% (563/772)

【環境】Windows10 Enterprise 2016 LTSB
【状況】
Windows10には、フォルダのサイズを一覧にして表示する機能がありません。
フォルダのサイズを確認する場合、1つ、1つ プロパティからフォルダサイズを確認する以外にはありません。

フォルダサイズの一覧を表示する以下のようなソフトウェアがあることは存じていますが、「ソフトウェア導入申請」をして承認されてから、業務で使用しているパソコンで動作するのかという検証があって1つのソフトウェアを導入するのに1ヶ月かかる場合があります。
DiskInfo https://forest.watch.impress.co.jp/library/software/diskinfo/
Folder Size http://foldersize.sourceforge.net/
ディレクトリ毎サイズ一覧 https://www.vector.co.jp/soft/dl/win95/util/se052881.html

フォルダサイズを一覧表示したい理由については、空き領域が少なくなった場合、フォルダサイズの一覧を表示してサイズが大きいフォルダ内に不要なファイルなどがないか確認するために使用したいと考えています。ソフトウェアに関しては「ソフトウェア導入申請」が必要ですが、VBS、BATであれば利用制限されておらず、許可されています。

【ご教示いただきたい点】
フォルダサイズ一覧を表示するためのプログラムは、以下のものがありましたが、このプログラムをフォルダサイズが大きい順に並べ替えるにはどのようにしたらよいでしょうか。
https://pc-automation.tech/wp/list-folder-size/

質問者が選んだベストアンサー

  • 回答No.4

ベストアンサー率 42% (201/469)

ルートディレクトリ(フォルダ)、すなわち「C:\」や「D:\」には、システムフォルダが存在するので、エラーが出ます。

「z」サブプロシージャを、以下に置き換えてください。

Sub z
For Each f In gf.SubFolders
If f.Attributes <> 22 Then
c = c + 1
ReDim Preserve n(c)
ReDim Preserve s(c)
n(c) = f
s(c) = f.Size
Set gf = Nothing
Set gf = so.GetFolder(f)
Call z
End If
Next
End Sub

システムフォルダは、処理しないようにしました。
補足コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

ローカルディスクであったり、外付HDDを接続した場合、直下で実行するとエラーになりますが、ネットワークドライブの場合はエラーにはなりませんでした。

実行したい場所はネットワークドライブとローカルディスクになりますが、Cドライブは非表示にしているため、そこにファイル、フォルダを作成することはないので、問題はなく、ローカルディスクとしてEドライブがありますが、Eドライブ直下ではなく、E:\ユーザーIDの下にフォルダ、ファイルを作成するので大丈夫のようです。

3連休明けに実際の環境で試してみることにします。
投稿日時 - 2019-02-10 16:47:33
お礼コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

zサブプロシージャを置き換えましたが「行:5 文字:2 エラー:書き込みできません。コード:800A0046 」になります。
投稿日時 - 2019-02-10 16:32:20
たいせつな将来のこと。あえて、知らない人に聞いてみよう。

その他の回答 (全3件)

  • 回答No.3

ベストアンサー率 42% (201/469)

プログラムファイル(「~.vbs」ファイル)の存在する直下のフォルダから以下のすべてのフォルダを調べます。

プログラムファイルの存在するフォルダは調べていません。

プログラムファイルが存在する同じフォルダ内に「FolderSize.txt」という結果ファイルを作成し、「Finished!」と表示しますので、「OK」を押して、終了してください。

「FolderSize.txt」の内容は、「フルパス」<Tab>「フォルダサイズ」です。

もちろん、大きい順にソートしてあります。

なぜか、サイズが「0」のフォルダを書き出そうとすると、エラーが出たので、サイズが「0」のフォルダ(空白フォルダ)は、書き出していません(必要もないでしょうから)。

Option Explicit
Public c, f, gf, i, j, n(), s(), so, tx, x, y
Set so = CreateObject("Scripting.FileSystemObject")
Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
Set tx = so.OpenTextFile(gf & "\FolderSize.txt", 2, True)
c = - 1
Call z
Set gf = Nothing
For i = 0 to c - 1
For j = i + 1 to c
If s(i) < s(j) Then
x = s(i)
s(i) = s(j)
s(j) = x
y = n(i)
n(i) = n(j)
n(j) = y
End If
Next
Next
For i = 0 to c
If s(i) > 0 Then
tx.WriteLine n(i) & vbTab & s(i)
End If
Next
tx.Close
Set tx = Nothing
Set so = Nothing
MsgBox("Finished!")

Sub z
For Each f In gf.SubFolders
c = c + 1
ReDim Preserve n(c)
ReDim Preserve s(c)
n(c) = f
s(c) = f.Size
Set gf = Nothing
Set gf = so.GetFolder(f)
Call z
Next
End Sub

簡単な説明です。

Option Explicit

「厳密に」というような意味で、このオプションを設定すると、変数は、その使用の前に、必ず、「Dim」等によって、宣言しておかなければなりません。

Public c, f, gf, i, j, n(), s(), so, tx, x, y

今回はサブプロシージャと変数を共通で使いたかったので、「Dim」ではなく、「Public」を使っています。

Set so = CreateObject("Scripting.FileSystemObject")

ファイルやフォルダ、テキストファイルを扱えるようにしています。

Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))

プログラムファイル自身が存在するフォルダを取得しています。

Set tx = so.OpenTextFile(gf & "\FolderSize.txt", 2, True)

そのフォルダ内に「FolderSize.txt」というファイルを「書き込み専用」で新規作成しています。

c = - 1

カウント用変数の初期化。

Call z

「z」サブプロシージャを呼び出しています。

For i = 0 to c - 1
For j = i + 1 to c
If s(i) < s(j) Then
x = s(i)
s(i) = s(j)
s(j) = x
y = n(i)
n(i) = n(j)
n(j) = y
End If
Next
Next

フォルダサイズの大きい順にソートしています(もちろん、そのとき、フルパスも入れ替えています)。

For i = 0 to c
If s(i) > 0 Then
tx.WriteLine n(i) & vbTab & s(i)
End If
Next

フォルダサイズが「0」より大きいものだけをテキストファイルに書き出しています。

tx.Close
Set tx = Nothing
Set so = Nothing
MsgBox("Finished!")

テキストファイルを閉じ、終了処理のあと、「Finished!」と表示しています。

Sub z

「z」サブプロシージャの始まり。

For Each f In gf.SubFolders

最初は、プログラムファイルの存在するフォルダ直下のすべてのサブフォルダを調べます。

c = c + 1
ReDim Preserve n(c)
ReDim Preserve s(c)
n(c) = f
s(c) = f.Size

配列変数を用意し、サブフォルダのフルパスを「n」に、フォルダサイズを「s」に格納しています。

Set gf = Nothing
Set gf = so.GetFolder(f)
Call z

見つかったサブフォルダをゲット(取得)し、自分自身(「z」サブプロシージャ)を呼び出しています。

こうして、すべてのサブフォルダを調べています。

Next

を、すべてのサブフォルダで繰り返しています。
補足コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

検証機で動作確認してみました。

ローカルディスクであるEドライブで動作はしました。
個人利用として割り当てをしているネットワークドライブであるDドライブとLドライブでも動作はしました。

ネットワークドライブとしてメンバー共有で使用するOドライブの場合、以下の結果でした。

Oドライブ直下:フォルダサイズを出力するファイルは作成されるがファイルの中身になにも書き込まれない。
Oドライブから1階層目のフォルダ:フォルダサイズを出力するファイルは作成されるがファイルの中身になにも書き込まれない。

Oドライブ1階層目に新規でフォルダを作成した場合は、フォルダサイズを出力するファイルは作成され、ファイルの中身に書き込まれる。

Oドライブにある既存で存在しているフォルダは業務で使用しており、既存で存在しているフォルダを別の場所に移動して
フォルダだけ同じように作成して、その既存フォルダにあるデータだけ移した後に検証してみることを考えましたが、
検証の準備中、ファイルが見当たらないとなって業務に影響がある可能性があったため、それはできませんでした。

恐らく、EドライブとDドライブとLドライブは実際のユーザーの環境でもうまくいくと思っています。
部署で使用しているネットワークドライブは、直下では動作せず、フォルダ数が少なければ、動作するのではと思っています。
投稿日時 - 2019-02-12 21:55:15
お礼コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

ご教示いただいきましたプログラムをCドライブ直下において、実行したところ、「 Set tx = so.OpenTextFile(gf & "\FolderSize.txt", 2, True)」
の箇所で下記のエラーになりました。

外付HDDを接続して、外付HDDがDドライブとして認識されたので、ご教示いただきましたプログラムをDドライブ直下において実行しましたが、
下記のエラーになりました。

デスクトップ上で実行してみたところ、「FolderSize.txt」は作成されましたが、ファイルの中身は空でした。
Cドライブ、Dドライブ内のフォルダに置いた場合は、「FolderSize.txt」が作成されて中身にフォルダサイズが記載されていました。


行:5 文字:2 エラー:書き込みできません。コード:800A0046
投稿日時 - 2019-02-10 14:12:15
  • 回答No.2

ベストアンサー率 67% (83/123)

ご提示いただいたプログラムを参考に、書き換えたVBSプログラムを示します。
どのような基準で並べ替えるのか分からなかったため、全てのフォルダサイズをフラットな状態で比較して並べています。
-----------------------------------------
'変数の宣言を強制
Option Explicit

'変数objFsoを宣言
Dim objFso
'objFsoにScripting.FileSystemObjectのオブジェクトをセット
Set objFso = WScript.CreateObject("Scripting.FileSystemObject")

'変数objSubFolderを宣言
Dim objSubFolder
'objFolderにフォルダをセット
Set objSubFolder = objFso.GetFolder(".\")


'変数writeFileを宣言
Dim writeFile
'書き込み用ファイル
Set writeFile = objFso.OpenTextFile("フォルダサイズ情報.html", 2, True)

'変数countを宣言と初期化
Dim count
'フォルダの深さカウント用
count = 0

Dim ArrayCounter
ArrayCounter = 0
ReDim keys(1)
ReDim lines(1)

'Forループ用変数
Dim i

writeFile.WriteLine "<head><style></style></head>"

'ShowFolderSize()メソッドを実行
Call ShowFolderSize(objSubFolder)

'ShowFolderSize()メソッド
Private Sub ShowFolderSize(ByRef objFolder)

'Long型に変換
Dim ISize
ISize = CLng(objFolder.Size * 0.001) * 0.001

'writeFile.WriteLine FormatNumber(ISize) & "MB" & "\t\t" & objFolder.Path
Dim npath
npath = Replace(objFolder.Path, " ", "_")
Dim splArray
splArray = Split(npath, "\")
Dim classname
classname = ""
For i = 0 to UBound(splArray) - 1
classname = classname & splArray(i)
Next
classname = Replace(classname, ":", "")
keys(ArrayCounter) = ISize
lines(ArrayCounter) = "<li class=""" & classname & """ data-path=""" & Replace(Replace(npath, "\", ""), ":", "") & """>" & FormatNumber(ISize) & "MB" & " : " & npath
ArrayCounter = ArrayCounter + 1

ReDim Preserve keys(ArrayCounter+1)
ReDim Preserve lines(ArrayCounter+1)

'自身のクラスを再起呼び出し
For Each objSubFolder In objSubFolder.subFolders

'フォルダの深さカウント用+1
count = count + 1

Call ShowFolderSize(objSubFolder)

'フォルダの深さカウント用-1
count = count - 1
Next
End Sub

QuickSort keys, lines, 0, UBound(keys)

Sub QuickSort(ByRef strKeys, ByRef strLines, lStart, lEnd)
Dim baseKey
Dim baseKeyTemp
Dim baseLineTemp
Dim i
Dim j

baseKey = strKeys((lStart + lEnd) \ 2) '中央値
i = lStart
j = lEnd
Do
'左から中央値より大きいものを検索
Do While strKeys(i) < baseKey
i = i + 1
Loop
'右から中央値より小さいものを検索
Do While strKeys(j) > baseKey
j = j - 1
Loop
If i >= j Then
Exit Do
End If
'データの交換
baseKeyTemp = strKeys(i)
strKeys(i) = strKeys(j)
strKeys(j) = baseKeyTemp
baseLineTemp = strLines(i)
strLines(i) = strLines(j)
strLines(j) = baseLineTemp
i = i + 1
j = j - 1
Loop
'左半分の処理
If lStart < i - 1 Then
QuickSort strKeys, strLines, lStart, i - 1
End If
'右半分の処理
If lEnd > j + 1 Then
QuickSort strKeys, strLines, j + 1, lEnd
End If
End Sub

For i = 0 to ArrayCounter
writeFile.WriteLine lines(ArrayCounter - i)
Next

writeFile.WriteLine "<script>"
writeFile.WriteLine "var li=document.getElementsByTagName('li'),style=document.getElementsByTagName('style')[0];for(item of li)item.addEventListener('click',function(){var e=this.getAttribute('data-path');style.innerHTML='li:not(.'+e+'){display: none;}'});"
writeFile.WriteLine "</script>"
msgbox("出力完了")
-----------------------------------------
出力は簡易的なHTML形式です。ブラウザで閲覧することを想定しており、各項目をクリックすることでフォルダの階層を進めるようになっています(戻ることはできません)。
KB単位の場合オーバーフローの恐れがあるため、MBでの表示に変更してあります。
プログラム中で用いているクイックソートのサブルーチンは下記URLのものを使用しています。
http://atomicsoft.blog.fc2.com/blog-entry-36.html
補足コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

お礼コメントの内容がNo.1の回答者へのものでした。申し訳ございません。

Cドライブにあるフォルダ内でご教示いただきましたプログラムを実行することができ、フォルダサイズが大きい順でソートされました。

Cドライブ、Dドライブ直下で実行した場合、ファイルに書き込みエラーになるため、確認してみることにします。
投稿日時 - 2019-02-10 14:43:32
お礼コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

以下のプログラムに「フォルダサイズ情報.txt」があることを見落としていました。ファイルには書き出されず、画面には表示されるので、画面表示だけと思っていました。

Cドライブ直下で行うと「行:21 文字:1 エラー:書き込みできません。コード:800A0046」になりましたので、何か要因がありそうなので確認してみることにします。
「Set writeFile = objFso.OpenTextFile("フォルダサイズ情報.txt", 2, True)」の箇所が要因のようです。


'変数の宣言を強制
Option Explicit

'変数objFsoを宣言
Dim objFso

'objFsoにScripting.FileSystemObjectのオブジェクトをセット
Set objFso = WScript.CreateObject("Scripting.FileSystemObject")

'変数objSubFolderを宣言
Dim objSubFolder

'objFolderにフォルダをセット
Set objSubFolder = objFso.GetFolder(".\")


'変数writeFileを宣言
Dim writeFile

'書き込み用ファイル
Set writeFile = objFso.OpenTextFile("フォルダサイズ情報.txt", 2, True)

'変数countを宣言と初期化
Dim count
'フォルダの深さカウント用
count = 0

'ShowFolderSize()メソッドを実行
Call ShowFolderSize(objSubFolder)



'ShowFolderSize()メソッド
Private Sub ShowFolderSize(ByRef objFolder)

'" -"をフォルダの深さ分だけ出力する
Dim n
n = 0
Do While n < count
writeFile.Write " -"
n = n + 1
Loop

'整数型に変換
Dim ISize
ISize = CLng(objFolder.Size) * 0.001
writeFile.WriteLine objFolder.Name & ": " & FormatNumber(ISize) & "K"

'自身のクラスを再起呼び出し
For Each objSubFolder In objSubFolder.subFolders

'フォルダの深さカウント用+1
count = count + 1

Call ShowFolderSize(objSubFolder)

'フォルダの深さカウント用-1
count = count - 1

Next

End Sub
投稿日時 - 2019-02-10 14:32:37
  • 回答No.1

ベストアンサー率 48% (4382/8998)

テキストファイルになるようなので、Excelにでも貼り付ければ良いのではないでしょうか。
お礼コメント
Engineer480907

お礼率 72% (563/772)

ありがとうございます。

以下のプログラムに「フォルダサイズ情報.txt」があることを見落としていました。ファイルには書き出されず、画面には表示されるので、画面表示だけと思っていました。

Cドライブ直下で行うと「行:21 文字:1 エラー:書き込みできません。コード:800A0046」になりましたので、何か要因がありそうなので確認してみることにします。
「Set writeFile = objFso.OpenTextFile("フォルダサイズ情報.txt", 2, True)」の箇所が要因のようです。


'変数の宣言を強制
Option Explicit

'変数objFsoを宣言
Dim objFso

'objFsoにScripting.FileSystemObjectのオブジェクトをセット
Set objFso = WScript.CreateObject("Scripting.FileSystemObject")

'変数objSubFolderを宣言
Dim objSubFolder

'objFolderにフォルダをセット
Set objSubFolder = objFso.GetFolder(".\")


'変数writeFileを宣言
Dim writeFile

'書き込み用ファイル
Set writeFile = objFso.OpenTextFile("フォルダサイズ情報.txt", 2, True)

'変数countを宣言と初期化
Dim count
'フォルダの深さカウント用
count = 0

'ShowFolderSize()メソッドを実行
Call ShowFolderSize(objSubFolder)



'ShowFolderSize()メソッド
Private Sub ShowFolderSize(ByRef objFolder)

'" -"をフォルダの深さ分だけ出力する
Dim n
n = 0
Do While n < count
writeFile.Write " -"
n = n + 1
Loop

'整数型に変換
Dim ISize
ISize = CLng(objFolder.Size) * 0.001
writeFile.WriteLine objFolder.Name & ": " & FormatNumber(ISize) & "K"

'自身のクラスを再起呼び出し
For Each objSubFolder In objSubFolder.subFolders

'フォルダの深さカウント用+1
count = count + 1

Call ShowFolderSize(objSubFolder)

'フォルダの深さカウント用-1
count = count - 1

Next

End Sub
投稿日時 - 2019-02-10 14:34:32
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

特集


OKWAVE若者応援スペシャル企画

ピックアップ

ページ先頭へ