繁体   English   中英

Windows批处理脚本,用于根据用于巨大数据量的文件名将文件移动到其他文件夹

[英]Windows Batch Script for moving files to different Folders based on File Name for Huge Data Volume

我大约有18万个文件,需要根据文件名移至文件夹。 文件具有不同的扩展名。 我需要获取所有以数字开头的文件名,并获取数字直到第一个“-”并创建一个文件夹。 用文件夹中的数字移动所有文件。 需要排除不以数字开头的文件。

样本数据:文件名

 123-ACBDHDJ.pdf 123-dhdjd.txt 5658-dgdjdk.txt 456477-gse.docx 

例如; 基于上面文件名中提到的上述数据,我要执行以下操作:

  • 使文件夹123,5658456477
  • 移动文件夹123中的前两个文件,文件夹5658中的第三个文件以及文件夹456477中的最后一个文件。

尝试以下脚本:

@echo off
setlocal enabledelayedexpansion
for %%A in (*.psd *.jpg *.html *.tif *.xls *.xlsx *.htm *.csv *.pdf *.docx *.TXT *.zip *.msg *.xlsb *.eml *.*) do (
   echo file found  %%A
   for /f "delims=" %%B in ("%%A") do set fname=%%~nB
   for /f "delims=" %%C in ("%%A") do set fextn=%%~xC
   for /f "tokens=1* delims=-" %%D in ("!fname!") do set folname=%%D
   echo folder name !folname!
   if not exist "!folname!" (
      echo Folder !folname! does not exist, creating
      md "!folname!"
   ) else (
      echo Folder !folname! exists
   )
   echo Moving file %%A to folder !folname!
   move "%%A" "!folname!"
   )
echo Finished
pause

当前面临的问题:

  1. 文件夹也是用字母数字字符创建的,我想忽略这些文件,只选择以数字开头的文件。
  2. 脚本运行时间过长,性能非常慢。 数据量很高,有18万条记录。

由于此数据量非常大,因此请使用批处理脚本来帮助您执行此操作或以更快的方式执行此操作。 提前致谢。

您正在使用许多不必要的代码,这会使您的批处理文件太慢。 我建议类似的东西:

@echo off

for %%A IN (*.*) do (
    if not "%%~fA" == "%~f0" (
        echo File found: %%A
        for /f "tokens=1* delims=-" %%B IN ("%%~nxA") do (
            md %%B>nul
            (move "%%~fA" "%%~dpA%%B")>nul
        )
    )
)
echo Finished
pause
exit /b %errorlevel%

您正在制作的其他循环似乎也没有用。 您可以直接使用%%~nA%%~xA等,请参见for /?输出for /? 以cmd为单位。

让我们考虑一下为什么要花很长时间。 您有128k个文件,运行4个循环,这意味着for循环自己将每个文件处理5次,即单独处理640 000个进程,然后为每个文件运行echo s,即更多的进程,然后检查是否文件夹存在,如果没有创建,则文件夹存在是另一个过程..我想您正在用这个方法。 您实际上正在运行一百万个过程来完成此任务。

也许我们摆脱了所有不必要的for循环,使用*而不是为每个文件命名,然后摆脱了延迟扩展,因为我们无需设置变量就可以摆脱掉:

@echo off
for %%i in (*) do (
    echo file found  %%i
    for /f "tokens=1* delims=-" %%a in ("%%i") do (
     if "%%a-%%b"=="%%i" (
      md %%a>nul
      move "%%~fi" %%a
   )
  )
 )
echo Finished
pause

至于名称和扩展名部分,则在设置后再也不会使用它们,如果您仍然想在某个地方使用文件的名称和扩展名,那么您只需要使用它们而无需设置vars:

@echo off
for %%i in (*) do (
   echo file found  %%i
   for /f "tokens=1* delims=-" %%a in ("%%i") do (
    if "%%a-%%b"=="%%i" (
       md %%a>nul
       move "%%~fi" %%a
       echo This is the file extension: %%~xi
       echo This is the filename: %%~na
       echo This is the filename, drive and path: %%~dpi
       echo This is the filename with full path: %%~fi
   )
  )
 )
echo Finished
pause

.bat文件脚本可能已经有了答案。 这是在PowerShell中执行此操作的方法。 测试脚本并正确移动文件后,请从Move-Item cmdlet中删除-WhatIf

$sourcedir = './s'
$destdir = './d'

Get-ChildItem -File -Path "$sourcedir/*" |
    ForEach-Object {
        if ($_.Name -match '^(\d+)-.*') {
            $ddir = Join-Path $destdir $Matches[1]
            if (-not (Test-Path -Path $ddir)) { New-Item -Name $ddir -ItemType Directory }
            Move-Item -Path $_.FullName -Destination $ddir -WhatIf
        }
    }

通过将脚本保存到文件(thefile.ps1)中并使用以下命令或将该命令放入.bat文件脚本,可以从cmd shell运行该命令。

powershell -NoLogo -NoProfile -File thefile.ps1

我将通过以下方式进行操作-参见代码中的所有解释性说明( rem ):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=%~dp0." & rem /* (directory containing all the files; `%~dp0` points to the
                     rem     parent directory of this batch script; to use the current
                     rem     working directory, simply specify a single `.`) */
set "_MASK=?*-*.*" & rem /* (search pattern to find files, matching only files with at
                     rem     least one hyphen in their names) */
set "_FILTER=^[0123456789][0123456789]*-" & rem /* (`findstr` filter expression;
                     rem     this matches only files whose name begin with one or more
                     rem     decimal digits followed by a hyphen) */

rem // Change to given root directory:
pushd "%_ROOT%" && (
    rem // Loop through all matching files:
    for /F "tokens=1* delims=-" %%E in ('
        rem/ Return files and filter out those with non-numeric prefix: ^& ^
            dir /B /A:-D "%_MASK%" ^| findstr /R /I /C:"%_FILTER%"
    ') do (
        rem // Try to create target directory:
        ECHO md "%%E" 2> nul
        rem // Move file into target directory:
        ECHO move /Y "%%E-%%F" "%%E\"
    )
    rem // Return from root directory:
    popd
)

endlocal
exit /B

在测试脚本的正确输出之后, 删除两个大写的ECHO命令!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM