youichirou
@youichirou

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

PowerShellで階層化されたフォルダの一括リネームをしたい

解決したいこと

PowerShellで、指定したパス以下にある「階層化された」フォルダの全ての名前の頭に番号を付けたいのです。

一般的にこういう場合は

$items = Get-ChildItem $sourceFolder -Recurse -Directory;

でフォルダのオブジェクト配列を取得し、

foreach ($item in $items) {
    Rename-Item -path $item.FullName -NewName ($targetnumber + $item.Name);
}

で順番にリネームするのが考えられるわけですが、階層化されたフォルダの場合うまくいきません。

発生している問題

以下のようなtemp以下にいくつかフォルダがある構成だとして

D:¥temp¥
D:¥temp¥hoge¥
D:¥temp¥hoge¥fuga¥
D:¥temp¥hoge¥fuga¥piyo¥

ゴールとしてはD:¥temp¥をスクリプトで指定し、"123"を付加し、以下のようになってほしいのですが、

D:¥temp¥
D:¥temp¥123hoge¥
D:¥temp¥123hoge¥123fuga¥
D:¥temp¥123hoge¥123fuga¥123piyo¥

多くの場合、上の階層のフォルダの名前が変わった段階(★)で、下位のフォルダのパスが変わってしまいますから、変更元のフォルダが見つからないエラーになってしまいます。

D:¥temp¥
D:¥temp¥123hoge¥ ←★
D:¥temp¥hoge¥fuga¥ ←エラー
D:¥temp¥hoge¥fuga¥piyo¥ ←エラー
Rename-Item : 'D:¥temp¥hoge¥fuga¥' の項目は存在しないため、名前を変更できません。
発生場所 test.ps1:100 文字:7
+ ...             Rename-Item -path $item.FullName -NewName ($target ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Rename-Item]、PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand

解決方法について

この場合、やはりループ1回でやろうとせず、再帰のような形でやるしかないのでしょうか。
オブジェクト配列を末尾からリネームするとか、パスの文字列長で降順ソートができると良いかと思うのですが、ちょっと現在やり方が見つけられずにいます。

皆様のお知恵を拝借できないものでしょうか。

0

2Answer

オブジェクト配列を末尾からリネームする

これで実現できそうです。
ディレクトリ名を再帰的に得てフルパスの文字列にしてから(ここ重要)逆順でソートします。
これで親ディレクトリの方が必ず後に来ることになります。

$directories = dir -Recurse -Directory | % { $_.FullName } | Sort-Object -Descending

あとは先頭から処理していくだけです。せっかく DirectoryInfo オブジェクトにしたので MoveTo() を使いましたが、リネームは好きな方法を使ってください。

$directories | % {
  $d = New-Object System.IO.DirectoryInfo($_)
  $dest = $d.Parent.FullName + "\" + "123" + $d.Name
  $d.MoveTo($dest)
}
1Like

自己回答ですが、素直に

[array]::Reverse($items);

で逆順にすることでひとまずうまくいきました。
ただ、Get-Childitemの順番が保証されているならいいのですが、たまに順番が入れ替わることがあるならエラーになるかも知れませんね。

0Like

Your answer might help someone💌