web-dev-qa-db-ja.com

Windows:ファイル名の正規表現を使用したファイルのコピー/移動?

私は基本的にしたい実行する:

C:\>xcopy [0-9]{13}\.(gif|jpg|png) s:\TargetFolder /s

xcopyが正規表現のファイル名検索をサポートしていないことは知っています。

PowerShellにファイルをコピーするためのCmdletがあるかどうかを確認する方法がわかりません。もしそうなら、それが正規表現のファイル名マッチングをサポートしているかどうかを調べる方法。

正規表現のファイル名を一致させて再帰的なファイルのコピー/移動を実行する方法を誰かが考えることができますか?

10
Ian Boyd

できる限りすべてのPowershellコマンドを使用するのが好きです。少しテストした後、これが私ができる最善の方法です。

$source = "C:\test" 
$destination = "C:\test2" 
$filter = [regex] "^[0-9]{6}\.(jpg|gif)"

$bin = Get-ChildItem -Path $source | Where-Object {$_.Name -match $filter} 
foreach ($item in $bin) {Copy-Item -Path $item.FullName -Destination $destination}

最初の3行は、これを読みやすくするためのものです。必要に応じて、実際のコマンド内で変数を定義できます。このコードサンプルの鍵は、正規表現の一致を受け入れるフィルターである「Where-Object」コマンドです。正規表現のサポートは少し奇妙であることに注意してください。左側にサポートされている文字があるPDF参照カード ここ が見つかりました。

[編集]

「@JohannesRössel」で述べたように、最後の2行を1行に減らすこともできます。

((Get-ChildItem -Path $source) -match $filter) | Copy-Item -Destination $destination

主な違いは、ヨハネスの方法はオブジェクトフィルタリングを行い、私の方法はテキストフィルタリングを行うことです。 Powershellを使用する場合、ほとんどの場合、オブジェクトを使用する方が適切です。

[編集2]

@smoknheapが述べたように、上記のスクリプトはフォルダー構造をフラットにし、すべてのファイルを1つのフォルダーに配置します。フォルダ構造を保持するスイッチがあるかどうかはわかりません。 -Recurseスイッチを試しましたが、役に立ちません。これを機能させる唯一の方法は、文字列操作に戻り、フィルターにフォルダーを追加することです。

$bin = Get-ChildItem -Path $source -Recurse | Where-Object {($_.Name -match $filter) -or ($_.PSIsContainer)}
foreach ($item in $bin) {
    Copy-Item -Path $item.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
    }

これを行うにはよりエレガントな方法があると確信していますが、私のテストからはうまくいきます。すべてを収集してから、名前の一致とフォルダオブジェクトの両方をフィルタリングします。文字列操作にアクセスするには、ToString()メソッドを使用する必要がありました。

[編集3]

ここで、パスを報告して、すべてが正しいことを確認します。 「Write-Host」コマンドを使用できます。これが何が起こっているかについてのいくつかのヒントを与えるコードです。

cls
$source = "C:\test" 
$destination = "C:\test2" 
$filter = [regex] "^[0-9]{6}\.(jpg|gif)"

$bin = Get-ChildItem -Path $source -Recurse | Where-Object {($_.Name -match $filter) -or ($_.PSIsContainer)}
foreach ($item in $bin) {
    Write-Host "
----
Obj: $item
Path: "$item.fullname"
Destination: "$item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
    Copy-Item -Path $item.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
    }

これにより、関連する文字列が返されます。どこかに何も表示されない場合は、どのアイテムに問題があるかがわかります。

お役に立てれば

5
Doltknuckle

PowerShellは、そのタスクに最適なツールです。コピープロセスには Copy-Item コマンドレットを使用できます。複雑なコピーコマンド用の他のコマンドレットとパイプラインすることができます ここ はまさにそれをした人です:)

正規表現は、System.Text.RegularExpressions名前空間の.NET RegExクラスを使用します。これらのクラスには クイックハウツー があります

PowerShellには -matchおよび-replace演算子 もあり、copy-itemでパイプライン化するときに使用できます。

RegEx自体を作成するのに役立つツールもあります。 正規表現バディ

3
armannvg

アイデアとして、いくつかの作業が必要です

dir -r | ?{$ _ -match '[0-9] {13} \。(gif | jpg | png)'} | %{xcopy $ _。fullname c:\ temp}

0
user33788