「ファイルサーバーの空きが残り1割を切りました」── この警告から始まる仕事は、たいてい憂鬱です。どこが容量を食っているのか分からない。誰も触っていない10年前のフォルダーが消してよいのか判断できない。そもそも誰がどこにアクセスできるのか、退職者の権限が残っていないか、聞かれても即答できない。エクスプローラーでプロパティを開いて回る調査は、数テラバイトの共有相手では終わりません。
この手の依頼で手を動かすたびに思うのは、ファイルサーバーの整理は「削除の技術」ではなく「棚卸しの技術」だということです。数字と一覧がないまま「消してよいですか」と聞いても、部門は絶対に首を縦に振りません。逆に「このフォルダーだけで800GB、うち3年以上更新のないファイルが620GB」という表があれば、話は一気に前へ進みます。
この記事では、中小企業の情シス・運用担当者を対象に、PowerShellでファイルサーバーの容量とアクセス権(ACL)を棚卸しし、CSVレポートに落とすまでの実務手順を整理します。方針は一貫して「まず読み取り、変更は最後に、バックアップと-WhatIfつきで」です。
1. まず結論
- 容量調査はGet-ChildItem -Recurse + Measure-Object -Sumが基本形です。いきなり全体を集計せず、第1階層のフォルダー単位で「太っている場所」の当たりを付けます。12
- アクセス拒否は握りつぶさず記録します。-ErrorAction SilentlyContinueで走査を止めない代わりに、-ErrorVariableで拒否された場所を必ず控えます。数えられなかった場所は「ゼロ」ではなく「不明」です。3
- 古いファイルの判定はLastWriteTime基準にします。NTFSの最終アクセス日時は既定で更新が無効化(またはシステム管理)されている環境が多く、判断材料として信頼できません。45
- 重複ファイルはGet-FileHash(既定SHA256)で「候補」を抽出します。先にサイズで絞ってからハッシュを計算するのがI/O節約の定石です。6
- ACLの棚卸しはGet-AclのAccessプロパティです。IdentityReference(誰)、FileSystemRights(何を)、IsInherited(継承か直接か)をCSVにし、AreAccessRulesProtectedで継承が切れた場所を検出します。78
- この記事で棚卸しするのはNTFSのアクセス許可です。共有(SMB)経由の実効アクセスは、共有側のアクセス許可とNTFS ACLの組み合わせで決まります。共有側はGet-SmbShareAccessで別途一覧化し、NTFSの台帳とセットで見てください。9
- CSVレポートの文字コードは明示します。Windows PowerShell 5.1のExport-Csv既定はASCIIで日本語が壊れ、PowerShell 7の既定はBOMなしUTF-8でExcelの既定動作と相性が悪いことがあります。1011
- 変更(Set-Acl)は棚卸しと部門確認が済んでから。icacls /saveでバックアップを取り、-WhatIfで対象を確認してから適用します。1213
2. 容量調査 ── どこが太っているのかを数字にする
最初にやることは、共有ルート直下のフォルダーごとの合計サイズです。Get-ChildItemで再帰的にファイルを列挙し、Measure-ObjectでLengthを合計します。12
$root = 'D:\share' # ファイルサーバー上で実行する想定。UNC越しの注意は第6章
$denied = @()
# 第1階層フォルダー単位で集計する ── 全体一括より「当たりを付ける」のが先
# ルート自体の列挙失敗も$deniedに入るよう、外側のGet-ChildItemにも同じ指定を付ける
$report = foreach ($dir in Get-ChildItem -LiteralPath $root -Directory `
-ErrorAction SilentlyContinue -ErrorVariable +denied) {
# アクセス拒否で止まらないようSilentlyContinue、ただし拒否は$deniedに蓄積する
# 列挙はパイプで直接Measure-Objectへ流す(変数に受けるとFileInfo全件をメモリに
# 保持することになり、ファイル数百万件級のフォルダーで苦しくなる)
$stats = Get-ChildItem -LiteralPath $dir.FullName -Recurse -File `
-ErrorAction SilentlyContinue -ErrorVariable +denied |
Measure-Object -Property Length -Sum
[PSCustomObject]@{
Folder = $dir.Name
SizeGB = [math]::Round([double]$stats.Sum / 1GB, 2)
FileCount = $stats.Count
}
}
# ルート直下に直接置かれたファイルも1行として数える(フォルダー単位の集計から漏れるため)
$rootStats = Get-ChildItem -LiteralPath $root -File `
-ErrorAction SilentlyContinue -ErrorVariable +denied |
Measure-Object -Property Length -Sum
if ($rootStats.Count -gt 0) {
$report += [PSCustomObject]@{
Folder = '(ルート直下)'
SizeGB = [math]::Round([double]$rootStats.Sum / 1GB, 2)
FileCount = $rootStats.Count
}
}
$report | Sort-Object SizeGB -Descending | Format-Table -AutoSize
# 「数えられなかった場所」を必ず残す ── ここが空でないなら集計は不完全
$denied | ForEach-Object { $_.TargetObject } | Sort-Object -Unique |
Set-Content -Path .\denied-paths.txt
ポイントは2つです。第一に、-ErrorAction SilentlyContinueは「エラーを見なかったことにする」スイッチではありません。表示を抑えて続行するだけで、エラー自体は発生しています。3 だから-ErrorVariableで受け止めます。変数名の前に+を付けると上書きではなく追記になるため、ループ全体の拒否を1つの変数に集められます。3 アクセス拒否されたフォルダーは集計から漏れており、レポート上は実際より小さく見えます。denied-paths.txtが空でないなら、その旨を必ずレポートに添えてください。エラー処理の設計をもう一段深くやるなら、同時公開の「PowerShellのエラー処理と再実行設計」が参考になります。
第二に、深い階層の問題です。長年運用された共有には、パスが260文字(MAX_PATH)を超える場所がほぼ確実にあり、ツールによってはそこで列挙が失敗します。14 走査結果に不自然な欠けがあるときは、まずパス長を疑ってください。この制限の全体像と対処は「MAX_PATHとWindowsのパス・ファイル名の落とし穴」にまとめています。
3. 古いファイルと重複候補 ── 削除ではなく一覧化から
3.1. 「3年触っていないファイル」を一覧にする
太っている場所が分かったら、次は「消せる候補」の材料集めです。基準に使うのはLastWriteTime(最終更新日時)です。
$cutoff = (Get-Date).AddYears(-3)
# 3年以上更新のないファイルの一覧。削除はしない ── まず部門に見せる材料を作る
# 列挙に失敗した場所も後で開示するため-ErrorVariableで記録する
Get-ChildItem -LiteralPath $root -Recurse -File `
-ErrorAction SilentlyContinue -ErrorVariable oldEnumErrors |
Where-Object LastWriteTime -lt $cutoff |
Select-Object FullName, LastWriteTime,
@{ Name = 'SizeMB'; Expression = { [math]::Round($_.Length / 1MB, 2) } } |
Sort-Object SizeMB -Descending |
Export-Csv -Path .\old-files.csv -NoTypeInformation -Encoding utf8BOM # 5.1ならUTF8(どちらもBOM付き)
# 列挙できなかった場所は一覧が「完全に見える」のを防ぐため必ず開示する
$oldEnumErrors | ForEach-Object { $_.TargetObject } |
Set-Content -Path .\old-files-uninspected.txt
「最終アクセス日時(LastAccessTime)を使えば『読まれてもいない』ことまで分かるのでは」と考えたくなりますが、これは罠です。NTFSでは最終アクセス日時の更新が性能に影響するため、fsutil behaviorコマンドとレジストリ(NtfsDisableLastAccessUpdate)で更新の有効/無効が制御されており4、Windows Vista以降は既定で無効(近年のWindows 10以降はシステム管理で、サーバーでは無効)とされています。5 つまり実際には開かれているのに日時が古いままというファイルが普通に存在します。棚卸しの説明資料には「最後に内容が変更された日」であるLastWriteTimeを使い、その意味も明記しておくと、部門との会話がこじれません。
3.2. 重複ファイルの「候補」を挙げる
共有フォルダーには「最終版」「最終版_修正」「コピー 〜」が大量に堆積します。内容が同一かどうかはGet-FileHashで判定できます。既定のアルゴリズムはSHA256で、ハッシュ値が一致すればファイル内容は同一と判断できます。6
# 全ファイルのハッシュ計算はI/Oが重い。先に「同じサイズのファイル」だけに絞る
# 列挙に失敗した場所(アクセス拒否など)も後で開示するため-ErrorVariableで記録する
$candidates = Get-ChildItem -LiteralPath $root -Recurse -File `
-ErrorAction SilentlyContinue -ErrorVariable enumErrors |
Group-Object -Property Length |
Where-Object { $_.Count -ge 2 -and [long]$_.Name -gt 0 } | # サイズ0は除外
ForEach-Object { $_.Group }
# 絞った候補だけハッシュを計算し、一致するグループを重複「候補」として出力
$candidates |
Get-FileHash -ErrorAction SilentlyContinue -ErrorVariable hashErrors | # 既定はSHA256
Group-Object -Property Hash |
Where-Object Count -ge 2 |
ForEach-Object { $_.Group } |
Select-Object Hash, Path |
Export-Csv -Path .\duplicate-candidates.csv -NoTypeInformation -Encoding utf8BOM # 5.1ならUTF8
# 列挙できなかったフォルダーと、ロック中・読み取り権限なしなどでハッシュを
# 計算できなかったファイルは「調べられなかった」として必ず一覧に残す
# (黙って落とすと重複ゼロと区別できない)
@($enumErrors) + @($hashErrors) | ForEach-Object { $_.TargetObject } |
Set-Content -Path .\hash-uninspected.txt
あえて「候補」と呼んでいるのは、どちらを残すかの判断が技術ではなく業務の問題だからです。同一内容でも「部門Aの正本」と「部門Bの参照コピー」は意味が違うことがあります。機械的に消さず、一覧を持って関係者と話すところまでがこのスクリプトの守備範囲です。ハッシュという道具自体の性質(何が保証され、何が保証されないか)は「ハッシュ文字列から方式を見分ける実務手順」で整理しています。
4. アクセス権(ACL)の棚卸し ── 誰が何をできるかを表にする
容量と並ぶもう一つの棚卸し対象が権限です。Get-Aclはファイルやフォルダーのセキュリティ記述子を取得し、AccessプロパティからDACLのアクセス制御エントリ(ACE)一覧を読み取れます。7
# 共有ルートから2階層分のフォルダーのACLを棚卸しする
# 権限設計の「幹」は浅い階層に集中しているので、まずそこを確認する
$aclErrors = @() # +付き-ErrorVariableは追記のため、前回実行分を持ち越さないよう毎回初期化する
$targets = @(Get-Item -LiteralPath $root `
-ErrorAction SilentlyContinue -ErrorVariable +aclErrors) +
@(Get-ChildItem -LiteralPath $root -Directory -Recurse -Depth 1 `
-ErrorAction SilentlyContinue -ErrorVariable +aclErrors)
$aclReport = foreach ($t in $targets) {
# 取得失敗(読み取り不可・走査中の削除など)も後で開示できるよう記録する
$acl = Get-Acl -LiteralPath $t.FullName -ErrorAction SilentlyContinue -ErrorVariable +aclErrors
if (-not $acl) { continue }
if (@($acl.Access).Count -eq 0) {
# DACLが空(明示エントリゼロ)のフォルダーも行として残す。継承切れの情報が台帳から消えないように
[PSCustomObject]@{
Path = $t.FullName; Identity = '(エントリなし)'; Rights = $null; Type = $null
IsInherited = $null; Inheritance = $null
InheritanceBroken = $acl.AreAccessRulesProtected
}
continue
}
foreach ($ace in $acl.Access) {
[PSCustomObject]@{
Path = $t.FullName
Identity = $ace.IdentityReference # 誰(ユーザー/グループ)
Rights = $ace.FileSystemRights # 何ができるか
Type = $ace.AccessControlType # Allow / Deny
IsInherited = $ace.IsInherited # 親からの継承か、直接付与か
# 同じ権限でも「このフォルダーだけ」か「配下のファイル/フォルダーにも及ぶ」かを区別する
Inheritance = "$($ace.InheritanceFlags)/$($ace.PropagationFlags)"
InheritanceBroken = $acl.AreAccessRulesProtected # このフォルダーで継承を切っているか
}
}
}
$aclReport | Export-Csv -Path .\acl-report.csv -NoTypeInformation -Encoding utf8BOM # 5.1ならUTF8
# ACLを取得できなかった対象も台帳の穴として必ず開示する(他の調査と同じ流儀)
$aclErrors | ForEach-Object { $_.TargetObject } |
Set-Content -Path .\acl-uninspected.txt
このCSVを開いたら、次の観点でフィルタして異常を探します。
| 見るべき列 | 異常のサイン | 典型的な背景 |
|---|---|---|
| Identity | 個人ユーザー名が直接載っている | 「とりあえずこの人に権限を」の積み重ね。異動・退職で腐る |
| Identity | S-1-5-21-...のようなSIDのまま表示される |
削除済みアカウントの権限が残っている(掃除の第一候補) |
| IsInherited = False | 深い階層に直接付与のACEが点在する | その場しのぎの個別付与。設計から外れた例外 |
| InheritanceBroken = True | 継承が切られたフォルダー | 過去の「このフォルダーだけ見せたくない」対応。棚卸しの重点対象 |
| Type = Deny | 拒否ACEがある | 同じ条件なら拒否が許可に優先する。ただし明示ACEは継承ACEより先に評価されるため、明示の許可が継承の拒否に勝つ並びもある。影響はACEの由来まで見て、最終的には実効アクセスで確認する |
IsInheritedがFalseのエントリは「そのフォルダーで誰かが手作業で足した権限」であり、AreAccessRulesProtectedがTrueのフォルダーは「親の権限変更が届かない島」です。78 権限トラブルの多くはこの2つに集中するので、まずここから台帳化します。ひとつ限界も明記しておきます。この例は-Depth 1の浅い走査なので、それより深い階層で継承を切ったフォルダーは対象に入らず、エラーも出ません。継承切れを全数調査したくなったら、時間はかかりますが-Depthの制限を外して同じスクリプトを流すか、疑いのある部門フォルダーをルートに指定して再実行してください。なおGet-AclはSDDLという文字列形式でもセキュリティ記述子を表示できますが7、棚卸し目的ならAccessプロパティの表で十分です。SDDLの読解に踏み込むのは、この表で説明できない現象に出会ってからで遅くありません。
ひとつ実務的な注意を。CSVの文字コードは必ず明示してください。Windows PowerShell 5.1のExport-Csvは既定でASCII出力のため日本語が壊れます。10 PowerShell 7系の既定はutf8NoBOM(BOMなしUTF-8)で11、Excelでそのまま開くと文字化けする環境があります。部門に渡すファイルなら-Encoding UTF8BOM(5.1では-Encoding UTF8)のようにBOM付きUTF-8へ寄せるのが無難です。
5. 変更はどうやるか ── icaclsとSet-Aclの使い分け、バックアップと-WhatIf
棚卸しと部門確認が終わって、初めて変更のフェーズです。ここで道具が2系統あります。
| 用途 | 道具 | 理由 |
|---|---|---|
| 調査・レポート | Get-Acl | 結果がオブジェクトなのでフィルタ・CSV化が容易7 |
| 変更前バックアップ | icacls /save | ACLをファイルに保存し、/restoreでそのまま戻せる13 |
| 定型的な権限付与・削除 | icacls /grant, /remove | 1行で完結し、/tで再帰適用、継承の再有効化(/inheritancelevel)も可能13 |
| 複雑な条件付き変更 | Set-Acl | ルールをコードで組み立てられる。-WhatIf対応12 |
| 壊れたACLの立て直し | icacls /reset | 既定の継承ACLに置き換える(影響大。最後の手段)13 |
どちらを使うにしても、順序は固定です。バックアップ → -WhatIf(または対象確認) → 適用 → 事後確認。
# 1. 変更前にACLをファイルへ保存する(/tで配下すべて、/cでエラーがあっても継続)
icacls "D:\share\sales" /save "C:\aclbackup\sales-acl.txt" /t /c
# バックアップが取れていないのに変更へ進まない。icaclsの成否は終了コードで確認する
if ($LASTEXITCODE -ne 0) {
throw "ACLバックアップに失敗しました (icacls ExitCode=$LASTEXITCODE)。変更作業を中止します"
}
# 2. Set-Aclで変更する場合: 取得 → ルール編集 → 適用 の3段階
$path = 'D:\share\sales\estimate'
$acl = Get-Acl -LiteralPath $path
# 営業グループに変更権限を付与するルール(サブフォルダー・ファイルへ継承)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
'CONTOSO\SalesTeam', 'Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
# 追加付与はAddAccessRuleで行う。SetAccessRuleは同じユーザー/グループの既存Allowルールを
# 置き換えるため、そのグループに設定済みだった細かい権限が黙って消えることがある
$acl.AddAccessRule($rule)
# 3. まず-WhatIfで「どこに適用されるか」を確認してから、本実行に進む
Set-Acl -LiteralPath $path -AclObject $acl -WhatIf
# 問題なければ: Set-Acl -LiteralPath $path -AclObject $acl
Set-Aclは「Get-Aclで取ったセキュリティ記述子をモデルとして適用する」動きをするため12、取得と適用の間で対象を間違えると、意図しないACLの丸ごと置き換えになります。上のように取得パスと適用パスを同じ変数で持つ、適用前に-WhatIfを挟む、という地味な習慣が事故を防ぎます。継承を切る操作(SetAccessRuleProtection)も同じ枠組みでできますが12、第4章で見たとおり継承切れは将来の管理コストになるので、新設は本当に必要な場所に限定してください。
この一連の作業を定期実行のスクリプトに育てるときの設計(SupportsShouldProcess、証跡の残し方、タスクスケジューラ登録)は「PowerShellスクリプト応用 ── ログ調査・アーカイブ・レポート化を安全に自動化する」で扱った型がそのまま使えます。
6. どこで実行するか ── UNC越しの走査と実行アカウント
最後に、意外と結果を左右する「実行場所と実行者」の話です。
- 大規模走査はサーバー上で実行するのが原則です。UNCパス(
\\fs01\share)越しの再帰列挙は、ファイル1つごとのメタデータ取得がネットワーク往復になるため、数十万ファイル規模では所要時間が桁で変わります。管理端末からやりたい場合は、PowerShell Remotingでスクリプトをサーバー側で動かし、結果のCSVだけ回収する構成が実務的です。やり方は同時公開の「PowerShell Remoting(WinRM)入門」を参照してください。 - 結果は実行アカウントの権限のスナップショットです。アクセスできない場所は列挙からもGet-Aclからも漏れます。調査は管理者権限のアカウントで行い、それでも拒否された場所(第2章のdenied-paths.txt)を「調査できていない場所」として報告に含めます。
- UNC越しに実行する場合は、資格情報とセッションの罠にも注意が必要です。ドライブ文字はログオンセッション単位である、同一サーバーへ複数の資格情報で接続できない(エラー1219)など、共有アクセス特有の落とし穴は「ネットワークドライブとUNCパスの落とし穴」にまとめています。
7. 実務の定石(判断表)
| 論点 | 選択肢 | 判断の目安 |
|---|---|---|
| 容量調査の範囲 | 全体一括 / 第1階層ごと | まず浅い階層で当たりを付け、太い場所だけ深掘りする12 |
| エラーの扱い | 停止 / 無視 / 記録して継続 | SilentlyContinue + ErrorVariableで「継続しつつ全記録」。拒否地帯はレポートに明記3 |
| 古いファイルの基準 | LastAccessTime / LastWriteTime | アクセス日時は更新無効の環境が多く不採用。更新日時+期間で部門と合意45 |
| 重複検出 | 全ファイルハッシュ / サイズで絞ってからハッシュ | ハッシュはI/Oが重い。同一サイズのグループだけ計算する6 |
| ACL調査の深さ | 全フォルダー / 浅い階層+継承切れの場所 | 継承が生きていれば親を見れば分かる。IsInherited=FalseとProtected=Trueを重点に78 |
| 権限変更の道具 | icacls / Set-Acl | 定型変更とバックアップはicacls。条件分岐を伴う一括処理はSet-Acl+-WhatIf1312 |
| 削除の実行 | 即削除 / 隔離→観察→削除 | 一覧を部門確認後、まず隔離フォルダーへ移動し、一定期間問題がなければ削除 |
8. まとめ
- ファイルサーバー整理は削除ではなく棚卸しから。第1階層の容量ランキング、古いファイル一覧、重複候補、ACL台帳の4点セットをCSVで作り、それを材料に部門と話します。
- 走査はSilentlyContinueで止めない代わりに、ErrorVariableで拒否された場所を必ず記録します。数えられなかった場所は「ゼロ」ではなく「不明」です。
- 古さの判定はLastWriteTime基準。NTFSの最終アクセス日時は更新が無効な環境が多く、信頼できません。
- 重複はサイズで絞ってからGet-FileHash(既定SHA256)。一致は「候補」であり、残す判断は業務側と行います。
- ACLはGet-AclのAccessをCSV化し、個人直付け・SIDのみのエントリ・継承切れ(AreAccessRulesProtected)を重点確認します。SDDLには深入り不要です。
- 変更はicacls /saveでバックアップ → -WhatIfや対象確認 → 適用 → 事後確認の順。大規模走査はサーバー上(またはRemoting経由)で、管理者権限で実行します。
関連記事
- ネットワークドライブとUNCパスの落とし穴 ── 業務アプリでファイルサーバー(共有フォルダ)を扱う実務
- MAX_PATHとWindowsのパス・ファイル名の落とし穴 ── 260文字制限、予約名、末尾ドット、大文字小文字
- PowerShell Remoting(WinRM)入門 ── 複数台のWindowsを一括管理する
- PowerShellのエラー処理と再実行設計
- PowerShellスクリプト応用 ── ログ調査・アーカイブ・レポート化を安全に自動化する
- ハッシュ文字列から方式を見分ける実務手順
関連する相談領域
合同会社小村ソフトでは、ファイルサーバーの容量・権限の棚卸しスクリプトの作成支援、権限設計の見直しに伴う調査、定期レポートの自動化(タスクスケジューラ運用まで)を扱っています。「まず現状を数字にしたい」という段階からのご相談も歓迎です。
参考リンク
-
Microsoft Learn, Get-ChildItem. Get-ChildItemによる項目列挙、-Recurseによる再帰と-Depthによる深さ制限、-Recurse使用時はワイルドカード解釈を避けるため-LiteralPathで対象を指定するのが推奨されることについて。 ↩ ↩2 ↩3
-
Microsoft Learn, Measure-Object. Measure-Objectが-Property Length -Sumなどでファイルサイズの合計・最大・最小・平均を計算できること、Get-ChildItemと組み合わせたディレクトリ内ファイルの集計例について。 ↩ ↩2 ↩3
-
Microsoft Learn, about_CommonParameters. -ErrorAction SilentlyContinueがエラー表示を抑止して実行を継続すること、-ErrorVariableで指定変数にエラーレコードが格納されること、変数名の前に+を付けると上書きではなく追記になることについて。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, fsutil behavior. NTFSの最終アクセス日時(Last Access Time)更新の有効/無効がfsutil behaviorのdisablelastaccessパラメーターとNtfsDisableLastAccessUpdateレジストリ値で制御されること、更新の無効化がファイル/ディレクトリアクセスの速度向上のために用意されていることについて。 ↩ ↩2 ↩3
-
Microsoft Learn, [MS-FSA]: Appendix A: Product Behavior. Windows Vista以降でNTFS/ReFSの最終アクセス日時更新が既定で無効であること、Windows 10 v1803以降はシステム管理となり、サーバーシステムでは最終アクセス日時の更新が常に無効化されることについて。 ↩ ↩2 ↩3
-
Microsoft Learn, Get-FileHash. Get-FileHashの既定アルゴリズムがSHA256であること、ハッシュ値が一致する2つのファイルは内容も同一と判断できること、ファイル名や拡張子を変えてもハッシュ値は変わらないことについて。 ↩ ↩2 ↩3
-
Microsoft Learn, Get-Acl. Get-Aclがファイルやリソースのセキュリティ記述子を取得すること、既定でDACLのアクセス制御エントリ一覧(Access)を表示すること、SDDL形式(Sddlプロパティ)でも取得できることについて。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, ObjectSecurity.AreAccessRulesProtected Property. AreAccessRulesProtectedプロパティが、セキュリティ記述子のDACLが保護されている(親からの継承を受けない)かどうかを返すことについて。 ↩ ↩2 ↩3
-
Microsoft Learn, about_Character_Encoding. Windows PowerShell(5.1)ではcmdletごとの既定エンコーディングが不統一で、Export-CsvはASCIIでファイルを作成すること、PowerShell 6以降は既定がutf8NoBOMに統一されたことについて。 ↩ ↩2
-
Microsoft Learn, Export-Csv. Export-Csvがオブジェクトの各プロパティを列としたCSVファイルを作ること、PowerShell 7系での-Encodingの既定値がUTF8NoBOMであり、UTF8BOMなどを明示指定できることについて。 ↩ ↩2
-
Microsoft Learn, Set-Acl. Set-AclがAclObjectで渡したセキュリティ記述子をモデルとして対象のACLを変更すること、-WhatIf/-Confirmに対応すること、FileSystemAccessRuleを作成してSetAccessRule()で追加する手順、SetAccessRuleProtection()による継承の無効化(既存の継承ルール保持の選択つき)の例について。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, icacls. icaclsがDACLの表示・変更を行うコマンドであること、/saveでACLをファイルに保存し/restoreで適用(復元)できること、/t(再帰)・/c(エラー時継続)・/grant・/remove・/reset・/inheritancelevelなどの主要オプションについて。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Maximum Path Length Limitation. Windows APIのパス長上限MAX_PATHが260文字であること、レジストリのLongPathsEnabledとアプリ側のlongPathAware宣言の両方が揃った場合のみ多くのWin32関数で制限が緩和されることについて。 ↩
関連する記事
同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。
PowerShellでの資格情報の安全な扱い ── 平文パスワードをスクリプトから追放する
PowerShellスクリプトに埋め込まれた平文パスワードを安全な保管へ移行する実務手順を整理します。Get-CredentialとPSCredential、SecureStringの実像と限界、Export-ClixmlによるDPAPI保存が同一ユーザー・同一マシン限定で...
PowerShell Remoting(WinRM)入門 ── 複数台のWindowsを一括管理する
PowerShell Remoting(WinRM)で複数台のWindowsを一括管理する入門。仕組みとポート5985/5986、Enable-PSRemotingで起きること、ワークグループのTrustedHosts、Invoke-CommandとPSSession、se...
PowerShellの実行ポリシーとスクリプト署名 ── 「Bypassで蓋をする」運用から卒業する実務ガイド
PowerShellの実行ポリシーが「セキュリティ境界ではなく安全装置」である理由から、Restricted/RemoteSigned/AllSignedの違い、スコープとグループポリシーの優先順位、Zone.Identifier(Mark of the Web)とUnbl...
そのバッチファイル、PowerShellに移行すべき? ── cmd/bat資産の棚卸しと移行判断
社内に残るバッチファイル(bat)をPowerShellに移行すべきかを判断表で整理します。cmdは廃止予定がない一方VBScriptは段階的削除が公式発表済みという対比、エラーで止まらない・%ERRORLEVEL%の罠などbat特有の弱点、batからpowershell....
PowerShellスクリプトの引数設計とモジュール化 ── 「動くスクリプト」から「人に渡せるスクリプト」へ
PowerShellスクリプトを他人に渡せる品質に引き上げる実務手順を整理します。paramブロックと[CmdletBinding()]による高度な関数化、型指定とMandatory、ValidateSetなどの入力検証、パイプライン入力、コメントベースヘルプ、-WhatI...
関連トピック
このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。
Windows技術トピック
Windows 開発、不具合調査、既存資産活用の技術トピックをまとめた入口です。
このテーマがつながるサービス
この記事は次のサービスページにつながります。近い入口からご覧ください。
Windowsアプリ開発
業務アプリ、装置連携、通信ツールなどの Windows ソフト開発を支援します。
よくある質問
この記事のテーマについて、相談時によくある質問をまとめています。
- PowerShellでフォルダーごとの合計サイズを調べるにはどうしますか?
- Get-ChildItemで-Recurse付きでファイルを列挙し、Measure-Objectの-Property Length -Sumで合計します。全体を一気に集計するのではなく、まず共有ルート直下の第1階層フォルダー単位で集計して「太っている場所」の当たりを付けるのが実務的です。その際-ErrorAction SilentlyContinueと-ErrorVariableを併用し、アクセス拒否で数えられなかった場所を必ず記録してください。エラーを黙って握りつぶすと、集計から漏れた場所が「サイズゼロ」に見えてしまいます。
- 古いファイルの判定にLastAccessTime(最終アクセス日時)を使ってよいですか?
- 推奨しません。NTFSでは性能上の理由から最終アクセス日時の更新が既定で無効化(またはシステム管理)されている環境が多く、実際にはファイルが読まれていても日時が更新されないことがあるためです。棚卸しの基準にはLastWriteTime(最終更新日時)を使い、「最後に内容が変更されてからの経過期間」として部門に提示するのが安全です。アーカイブ判断は機械的に行わず、一覧を関係者に確認してもらってから進めてください。
- Get-Aclで何が分かりますか?SDDLは読む必要がありますか?
- Get-Aclはファイルやフォルダーのセキュリティ記述子を取得し、Accessプロパティから「誰が(IdentityReference)」「何を(FileSystemRights)」「許可か拒否か(AccessControlType)」「継承か直接付与か(IsInherited)」を読み取れます。AreAccessRulesProtectedを見れば、そのフォルダーで継承が切られているかも分かります。SDDLという文字列形式もありますが、棚卸し目的ならAccessプロパティをCSVに出す方が関係者と共有しやすく、SDDLに深入りする必要はありません。
- ACLの変更はPowerShellのSet-Aclとicaclsのどちらでやるべきですか?
- 調査・レポートはオブジェクトとして扱えるGet-Acl、変更の実務はicaclsを第一候補にするのが使い分けの目安です。icaclsは/saveでACLをファイルに保存し/restoreでそのまま戻せるため、変更前のバックアップと切り戻しが簡単です。Set-Aclを使う場合はGet-Aclで取得→ルール編集→適用の3段階になり、-WhatIfで対象を確認してから実行します。いずれの場合も、棚卸しと関係部門への確認が済んでから変更に進むのが原則です。
- ファイルサーバーの調査はUNCパス越しに実行してよいですか?
- 少量なら問題ありませんが、数十万ファイル規模の全走査はネットワーク越しだと大幅に遅くなります。可能ならファイルサーバー上で直接(またはPowerShell Remotingで)実行し、結果のCSVだけを持ち帰る構成が効率的です。また、走査結果は実行アカウントの権限に依存します。アクセスできないフォルダーは列挙から漏れるため、管理者アカウントで実行したうえで、それでも拒否された場所を記録して「調査できていない場所」として報告に含めてください。
著者プロフィール
記事の著者プロフィールページです。
小村 豪
合同会社小村ソフト 代表
Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。
公開リンク