Powershell一次递归移动20,000个文件
Powershell recursively move 20,000 files at a time
我是 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[=17=]0001 [20,000 messages]
D:\My20kFiles[=18=]0002 [next 20,000 messages]
D:\My20kFiles[=19=]0003 [next 20,000 messages]
...etc
列出文件,将它们移动到名为 (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 来自我的代码块的帮助链接(如果可用):
Get-ChildItem
(在模块 Microsoft.PowerShell.Management
中)
ForEach-Object
Test-Path
(在模块 Microsoft.PowerShell.Management
中)
Move-Item
(在模块 Microsoft.PowerShell.Management
中)
以下脚本可测试并执行以下任务:
检查目标文件夹是否为空,如果不是则退出。
将移动文件操作记录到名为 log.txt 的文件以供稍后查看。
可以在测试模式下工作,提前知道会发生什么。
可以定义源文件夹-目标文件夹-增量值
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[=12=]0001 at counter=1
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
Creating new folder i:\My20kFiles[=12=]0002 at counter=6
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
Creating new folder i:\My20kFiles[=12=]0003 at counter=11
mv I:\myfiles.txt i:\My20kFiles[=12=]0003
mv I:\myfiles.txt i:\My20kFiles[=12=]0003
.................
更新:
我修改了代码:
添加日志文件作为参数。默认路径将是当前的 powershell 工作文件夹
$Testmode 最初是假的,所以你移动文件。您可以在测试模式下将参数 $Testmode=$true 传递给 运行(不移动到文件),您可以查看描述文件移动位置的日志文件。
您可以根据需要自定义代码
试试这个
$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 }
我是 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[=17=]0001 [20,000 messages]
D:\My20kFiles[=18=]0002 [next 20,000 messages]
D:\My20kFiles[=19=]0003 [next 20,000 messages]
...etc
列出文件,将它们移动到名为 (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 来自我的代码块的帮助链接(如果可用):
Get-ChildItem
(在模块Microsoft.PowerShell.Management
中)ForEach-Object
Test-Path
(在模块Microsoft.PowerShell.Management
中)Move-Item
(在模块Microsoft.PowerShell.Management
中)
以下脚本可测试并执行以下任务:
检查目标文件夹是否为空,如果不是则退出。
将移动文件操作记录到名为 log.txt 的文件以供稍后查看。
可以在测试模式下工作,提前知道会发生什么。
可以定义源文件夹-目标文件夹-增量值
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[=12=]0001 at counter=1
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
mv I:\myfiles.txt i:\My20kFiles[=12=]0001
Creating new folder i:\My20kFiles[=12=]0002 at counter=6
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
mv I:\myfiles.txt i:\My20kFiles[=12=]0002
Creating new folder i:\My20kFiles[=12=]0003 at counter=11
mv I:\myfiles.txt i:\My20kFiles[=12=]0003
mv I:\myfiles.txt i:\My20kFiles[=12=]0003
.................
更新:
我修改了代码: 添加日志文件作为参数。默认路径将是当前的 powershell 工作文件夹
$Testmode 最初是假的,所以你移动文件。您可以在测试模式下将参数 $Testmode=$true 传递给 运行(不移动到文件),您可以查看描述文件移动位置的日志文件。
您可以根据需要自定义代码
试试这个
$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 }