マルウェアでPowerShellが使われる場合があると聞いたことがあったので、セキュリティの知識向上のためPowerShellの勉強(プログラミング)を始めました。何を作っていいかわからなかったので、とりあえず自分が使いそうなファイル操作のサンプルを試しに作りました。
ファイル名の数値を同じ桁数にする
対象となるフォルダのツリー構造で表示します。
C:.
│ oya_1.txt
│ oya_10.txt
│ oya_11.txt
│ oya_2.txt
│ oya_3.txt
└─ko
│ ko_1.txt
│ ko_10.txt
│ ko_11.txt
│ ko_2.txt
│ ko_3.txt
└─mago
mago_1.txt
mago_10.txt
mago_11.txt
mago_2.txt
mago_3.txt
ファイル名に数値を使っている場合、上のような順番に並んでしまい見栄えが良くない場合があります。数値を3桁に変更することにより、並び順を変えて見やすくします。
Get-ChildItem -Recurse | ForEach-Object {if ($_.Name -match '\d+') {
$n = $_.Name -split $Matches[0],2
Rename-Item -Path $_.FullName -NewName ($n[0]+'0'*(3-$Matches[0].Length)+$Matches[0]+$n[1])
}}
C:.
│ oya_001.txt
│ oya_002.txt
│ oya_003.txt
│ oya_010.txt
│ oya_011.txt
└─ko
│ ko_001.txt
│ ko_002.txt
│ ko_003.txt
│ ko_010.txt
│ ko_011.txt
└─mago
mago_001.txt
mago_002.txt
mago_003.txt
mago_010.txt
mago_011.txt
全角で書かれたファイル名を半角にする
対象となるフォルダをツリー構造で表示します。
C:.
│ TEST1.txt
└─FOLDER1
│ TEST2.txt
└─FOLDER2
TEST3.txt
ファイルとフォルダを全角から半角に変換します。
using namespace Microsoft.VisualBasic
Add-Type -AssemblyName 'Microsoft.VisualBasic'
Get-ChildItem -Recurse | ForEach-Object { Rename-Item -Path $_.FullName -NewName ([Strings]::StrConv($_.Name,[VbStrConv]::Narrow)) }
C:.
│ TEST1.txt
└─FOLDER1
│ TEST2.txt
└─FOLDER2
TEST3.txt
サブフォルダを含むファイル名の出力
子や孫フォルダを含むファイル名を出力します。csv形式で出力する場合と、フルパスのみ出力する場合の2パターンを記載します。なお、文字化け対策としてUTF-8でコード変換して出力しています。
Get-ChildItem *.txt -Attributes Archive -Recurse | Select-Object DirectoryName,BaseName,Extension,Length,LastWriteTime | Export-Csv -Encoding UTF8 output.csv
# TYPE Selected.System.IO.FileInfo
"DirectoryName","BaseName","Extension","Length","LastWriteTime"
"C:\Users\test\FOLDER1\FOLDER2","TEST3",".txt","10","2021/05/01 12:00:00"
"C:\Users\test\FOLDER1","TEST2",".txt","10","2021/05/01 12:00:00"
"C:\Users\test","TEST1",".txt","10","2021/05/01 12:00:00"
Get-ChildItem *.txt -Attributes Archive -Recurse | ForEach-Object { $_.FullName } | Set-Content output.dat
C:\Users\une\test3\FOLDER1\FOLDER2\TEST3.txt
C:\Users\une\test3\FOLDER1\TEST2.txt
C:\Users\une\test3\TEST1.txt
ファイルに書かれているファイルを集める
先程出力したファイルoutput.dat
を元に、ファイルを現在のパスにコピーします。なお、同じファイル名がある場合はコピーしません。
Get-Content output.dat | ForEach-Object { if (Test-Path $_) { Copy-Item -Path $_ -Destination . } }
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2021/05/01 12:00 10 TEST1.txt
-a---- 2021/05/01 12:00 10 TEST2.txt
-a---- 2021/05/01 12:00 10 TEST3.txt
サブフォルダも含むファイル内容の検索
対象となるフォルダのツリー構造で表示します。
C:.
│ test1.txt
└─folder1
test2.txt
ABCDEFGHIJ
1234567890
abcde12345
ABCDEF
123456
ABC123
select-String
は正規表現も可能です。
Get-ChildItem -Recurse | Select-String -Pattern 'c\w' | Select-Object path,LineNumber,line
Path LineNumber Line
---- ---------- ----
C:\Users\une\test4\test1.txt 1 ABCDEFGHIJ
C:\Users\une\test4\test1.txt 3 abcde12345
C:\Users\une\test4\folder1\test2.txt 1 ABCDEF
C:\Users\une\test4\folder1\test2.txt 3 ABC123
おわりに
今回は(本当に初めてだったので)ファイル操作だけでしたが、次からはよりセキュリティに近いイベントログを集計したり、システムを自動操作できるスクリプトを組んでみたいと思います。