ls | %{} での $_が怪しいことがある、かも

なぜこんなことに

あるフォルダ内のファイルを全部7z圧縮して、元ファイルを削除するってことを下記スクリプトで実行したんです。

ls | %{& 'C:\Program Files\7-Zip\7z.exe' a "$_.7z" $_;remove-item $_ -Recurse -Verbose -force}

そしたら、生成された7zファイルまで綺麗さっぱり削除されてしまっていたっていう……!

その後、他のフォルダでテストしてみたんですが、7zファイルまで削除されてしまうようなケースは発生しません…。なにが起こったんだー?

実行中にlsで取得されていたリストが更新されてしまって、新たに生成した7zファイルもリストに入ってしまったとしか考えられないんだけれど…そんな事ってあるのかなぁ…。

対策

原因がよくわからないけど、再発されたら大変困るので、対策を考えました。

$dir=ls; $dir | %{& 'C:\Program Files\7-Zip\7z.exe' a ($_.fullname + ".7z") $_; remove-item $_.fullname -Recurse -Verbose -force}

lsの結果を変数$dirに確定させて更新される危険性を排除した形。ついでに、パスをfullnameで指定するように変更しています。

ls | %{& 'C:\Program Files\7-Zip\7z.exe' a ($_.fullname + ".7z") $_; remove-item $_.fullname -Exclude *.7z -Recurse -Verbose -force}

remove-itemが*.7zを削除しなければいいので、上記のように-Excludeオプション指定するだけでもOK。

しかし…

ほんまかーこれ?

remove-item $_*とか書いてしまっただけちゃうんか、というわけでもなさそうなんだよなー。というのは、*.7zファイルがスクリプト実行の最後の方でまとめて削除されていたから。
remove-item $_*なら、圧縮ファイル作成した後に逐次削除されていくもんなぁ。
とりあえず、覚えておこう。

PSVersion:2.0のお話です

コメントを残す