2016-10-26 1 views
1

私はPowershellの初心者です。私は、他の場所で処理できるようにデータを移動しようとしています。処理できるファイルの数に制限があります。私のソースフォルダには数百のサブフォルダがあり、各サブフォルダは最大100個のサブフォルダを持ち、合計で最大数百万の小さなファイルになります。ファイル名はエクスポートから一意の25桁の出力と見なされるため、チェックを除いて全体のプロセスを上げると、各移動で既存のファイル名をチェックする必要はありません。Powershellは一度に2万ファイルを再帰的に移動します

Powershellをソースパスからインクリメンタルな名前を付けられた20,000個のファイルのコピー先フォルダに移動する(コピーしない)ように自動化したいと思います。出力先のフォルダ名は、各出力先に20,000を超えるファイルしか持たず、既存のフォルダ名と重複しない限り、重要ではありません。

例:

出典:C:\ MyFilesフォルダには、各も100個のサブフォルダを持っている100個のサブフォルダを持っています。

C:\Myfiles\Folder000\Folder000A\file1.txt C:\Myfiles\Folder000\Folder000A\file2.txt C:\Myfiles\Folder000\Folder000A\file3.txt C:\Myfiles\Folder000\Folder000B\file1.txt C:\Myfiles\Folder000\Folder000B\file1.txt C:\Myfiles\Folder001\Folder000A\file1.txt ...etc

先D:\ My20Kfiles

D:\My20kFiles\000001 [20,000 messages] D:\My20kFiles\000002 [next 20,000 messages] D:\My20kFiles\000003 [next 20,000 messages] ...etc

+0

を試してみたいとあなたはコードをカスタマイズすることができます| -first 10 ';-) – LotPings

+0

右を選択するが、どのようにすることができますIループその出力を一度に1行ずつ移動して目的地に移動しますか?私は、最初にget-ChildItem -recurse -Filter * .txt -fileのように画面に出力するための完全なパスを得ることができることを知っています。選択 - 最初10000 | %{$ _。FullName} –

+1

明確にするには、ファイルをターゲットフォルダに移動する際に入力階層を_平坦化しても問題ありませんか?それはあなたのサンプルデータと異なり、 'file1.txt'のような一意でないファイル名を持っています – mklement0

答えて

0

あなたは `GCIを実行するときEyouはアイデアを得るか、この

$yourdir="C:\MyFiles" 
$yourdestdir="D:\My20Kfiles" 
$loop=20000 
$i=$loop; 
gci $yourdir -Recurse -File -Filter *.txt | %{$newdir="$yourdestdir\{0:d6}\" -f [math]::DivRem($i++, $loop, [ref]$null) ;new-item -Path $newdir -Force -ItemType Directory; Move-Item -Path $_.FullName -Dest $newdir -Force } 
+0

Ranを実行すると即座にプロンプ​​トが返され、出力がなく、$ yourdir –

+0

に使用されているテストサンプルのコピーディレクトリで何も処理されていないように見えて、C:\ MyFilesディレクトリに.txtファイルを保存しましたか?それは私のテストで動作します – Esperento57

+0

そして私の間違いは、私が拡張を修正することを怠った!これは完璧に動作しました! –

2

ファイルを一覧表示し、(counter ++/20000)という名前のフォルダに移動します。

gci "c:\myfiles" -R -File | mv -Dest {"c:\My20kFiles\{0:d6}\" -f [math]::DivRem($global:counter++, 20000, [ref]$null)} -Force -WhatIf 

未テスト。 Ymmv。 mvは-Forceでフォルダを作成します。実際に実行するには-WhatIfを削除してください。

実際にフォルダ内の20k個のファイルをチェックしたり、既存のフォルダ名が重複しているかどうかはチェックしません。しかし、原則が適用されます。

また、テストされていない20kファイルをフォルダに入れて、次の未使用フォルダ番号に移動します。

$FolderNumber = 0 
$FilesRemainingForThisFolder = 0 

Get-ChildItem "c:\myfiles" -Recurse -File | ForEach-Object { 

    if (0 -eq $FilesRemainingForThisFolder) 
    { 
     # Keep counting foldernumber until we get to a folder name that doesn't exist. 
     do { 
      $FolderNumber++ 
      $DestinationFolder = "c:\My20kFiles\{0:d6}\" -f $FolderNumber 
     } while ((Test-Path $DestinationFolder)) 

     mkdir $DestinationFolder 
     $FilesRemainingForThisFolder = 19999 
    } 
    else 
    { 
     Move-Item -LiteralPath $_.FullName -Destination $DestinationFolder -Force -WhatIf 
     $FilesRemainingForThisFolder-- 
    } 

} 

私のコードブロックから

自動生成PSのヘルプリンク(利用可能な場合):

+1

うまくいっています。現時点でのパイプラインであると評価されたスクリプト・ブロック・ブロック・オブ・ア・パラメータ・バリュー・オブ・ア・パラメータ・トリックについては知らなかった。 (これはどこに記載されていますか?)[Math] :: Floor() 'は、[Math] :: DivRem()の簡単な代替手段として提案しています(少なくともこの場合は、残り)。 – mklement0

+0

@ mklement0あなたは 'sort-object'の文脈でそれについて知っていますか?例えば'gci | sort --property {$ _。substring(3,5)} '名前の一部でファイルをソートするには?私はそれが文書化されているかどうか分かりませんが、このブログの投稿はありますが - https://learn-powershell.net/2014/10/11/using-a-scriptblock-parameter-with-a-powershell-function/ - MVP Dave Wyatt、コメントでは、それがうまく文書化されていないと言い、それがどのように機能するかについて語っている。編集:ジェフリースヌーバーはここでそれが起こるブログ:https://blogs.msdn.microsoft.com/powershell/2006/06/23/flexible-pipelining-with-scriptblock-parameters/ – TessellatingHeckler

+0

これを共有してくれてありがとう、ここに ' - ea sil ... 'が必要で、効果を見るには' gci | sort-property {$ _。Name.substring(1,1)} - サイレントに続行する – LotPings

0

次のスクリプトは、テスト可能であり、次のタスクを実行します。

チェックをターゲットフォルダが空の場合は、終了しそうでない場合。

後で見直されるように、動いているファイルアクションをlog.txtという名前のファイルに記録します。

テストモードで動作して、何が起こるかを事前に知ることができます。

あなたは、元のフォルダ-targetフォルダを定義することができます -

function Move-Files { 
    param ($Source ,$Targert,$Increment=5 , $TestMode, $Logfile) 

     $currentpath=pwd 
     if (!$LogFile) {$Logfile= "{0}\{1}" -f $currentpath,"log.txt" } 
     "log file is created in $logfile" 
     # check that destination folder is empty and create 
     if(!(Test-Path -Path $Targert)){ 
        $null=New-Item -ItemType directory -Path $Targert -Force 
      } 
     else 
     { 
      $targetFiles = get-childitem $Targert -Recurse -File 
      if ($targetFiles -ne $null) {"Target folder not empty, Please remove it";return} 
     } 


     $files=get-childitem $source -Recurse -File  
     $fileCounter=0 
     $folderCounter=0 
     $Nextfolder="00001" 
     "Moving {0} to {1}| Total Files: {2} | Increment:{3}" -f $Source, $Targert , $files.count,$increment |tee $Logfile 
     $files |foreach { 
      $fileCounter++ 
      if ((($fileCounter - 1) % $increment) -eq 0) 
      { 
       $folderCounter++ 
       $Nextfolder= "{0}\{1}" -f $targert, $folderCounter.ToString("000000")  
       "Creating new folder {0} at counter={1}" -f $Nextfolder,$fileCounter |tee -Append $Logfile 
       #create Folder 
       $null=New-Item -ItemType directory -Path $Nextfolder -Force 

       } 
       if ($testMode) 
       { 
       "mv {0} {1}" -f $_.FullName,$Nextfolder |tee -Append $Logfile 
       } 
       else 
       { 

       mv $_.FullName -Destination $Nextfolder -Force #-WhatIf 
       "mv {0} {1}" -f $_.FullName,$Nextfolder |tee -Append $Logfile 
       } 
     } 
    } 
を使用する方法インクリメント値:出力の

$source="i:\myfiles" 
    $targert="i:\My20kFiles" 
    $increment=5 # for a test, modify 20000 

    #run in test mode to know what will happen 
    $TestMode=$true # modify to $flase to actual moving files 

    Move-Files -Source $source -Targert $targert -Increment $increment -TestMode $TestMode 

サンプルを:(ログファイルに同じことを見つけますlog.txt)

Moving i:\myfiles to i:\My20kFiles| Total Files: 42 | Increment:5 
    Creating new folder i:\My20kFiles\000001 at counter=1 
    mv I:\myfiles\1.txt i:\My20kFiles\000001 
    mv I:\myfiles\10.txt i:\My20kFiles\000001 
    mv I:\myfiles\11.txt i:\My20kFiles\000001 
    mv I:\myfiles\12.txt i:\My20kFiles\000001 
    mv I:\myfiles\13.txt i:\My20kFiles\000001 
    Creating new folder i:\My20kFiles\000002 at counter=6 
    mv I:\myfiles\14.txt i:\My20kFiles\000002 
    mv I:\myfiles\15.txt i:\My20kFiles\000002 
    mv I:\myfiles\16.txt i:\My20kFiles\000002 
    mv I:\myfiles\17.txt i:\My20kFiles\000002 
    mv I:\myfiles\18.txt i:\My20kFiles\000002 
    Creating new folder i:\My20kFiles\000003 at counter=11 
    mv I:\myfiles\19.txt i:\My20kFiles\000003 
    mv I:\myfiles\2.txt i:\My20kFiles\000003 
    ................. 

更新:

コードを変更しました: ログファイルをパラメータとして追加します。デフォルトのパスは、現在のpowershellの作業フォルダになります。

$ Testmodeは最初は偽で、ファイルを移動します。パラメータ$ Testmode = $ trueを渡してテストモード(ファイルに移動しない)で実行し、ファイルの移動先を説明するログファイルを確認することができます。

あなたは

+0

20kファイルを各セットの新しい単一フォルダにまとめることは、私が望む結果です。オプションをありがとう - 私はこれらの例の両方を試みるとすぐに結果を返すだろう。 –

+0

私はあなたのコードを正しく使用していないでしょう。私はそれを保存し、スクリプトに変数を設定して実行し、引数を指定して実行し、出力もno log.txtも出力しない –

+0

log.txtはISEのデフォルトパスに作成されます。たとえば、c:\ temp \ log.txtというパスを定義できます。ファイルを移動するには、$ testmode = $ falseを設定します。 $ testmode = $ true(デフォルト)の場合、ファイルへの移動はしませんが、sourceとtargeの移動ファイルを記述するメッセージとともにlog.txtが作成されます。試して結果を教えてください。 –

関連する問題