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

时间:2019-02-04 22:36:08

标签: windows batch-file cmd

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

  

样本数据:文件名

123-ACBDHDJ.pdf

123-dhdjd.txt 

5658-dgdjdk.txt

456477-gse.docx

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

  • 制作文件夹 123 5658 456477
  • 移动文件夹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万条记录。

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

4 个答案:

答案 0 :(得分:0)

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

@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 /?的cmd输出。

答案 1 :(得分:0)

让我们考虑一下为什么要花很长时间。您有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

答案 2 :(得分:0)

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

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

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

powershell -NoLogo -NoProfile -File thefile.ps1

答案 3 :(得分:0)

我将通过以下方式进行操作-请查看代码中的所有解释性说明(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命令!