Powershell一次递归移动20,000个文件

时间:2016-10-26 20:18:43

标签: powershell batch-file increment move

我是Powershell的新手。我试图将数据移动到其他地方进行处理,这些数据在它可以处理的时候对文件数量有限制。我的源文件夹有数百个子文件夹,每个子文件夹最多也可能有100个子文件夹,总计高达数百万个小文件。假设文件名是导出的唯一25位输出,因此如果排除检查会加快整个过程,则无需在每次移动时检查现有文件名。

我想自动将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

3 个答案:

答案 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

未测试。因人而异。 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 :(得分: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最初为false,因此您移动文件。您可以传递参数$ Testmode = $ true以在测试模式下运行(不移动到文件),您可以查看描述文件移动位置的日志文件。

您可以根据需要自定义代码

答案 2 :(得分:0)

试试这个

 $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 }