繁体   English   中英

批处理:如何根据文件名将文件复制到目录

[英]BATCH: How can I copy files to directory based on file name

我要为自己工作的公司归档很多文件。 我对批处理脚本有点熟悉,但是我对它的理解还不够充分。

我正在尝试根据文件名的开头将一些文件复制到我们NAS上的文件夹中。 这些文件是7z文件,其结构将如下所示:

  • 5476宝马把手-A.7z
  • 5487雪佛兰-Imp.7z
  • 5986本田Lid-Upper.7z

等等

文件结构是这样的:开头的四个数字是我们公司的工作编号。 在我们的NAS上,我们有一个包含目录的存档目录,如下所示:

  • _5000-5999
  • _6000-6999

在这些文件夹的内部,每个文件夹将包含250个存档文件。 它们的格式如下:

  • _5000-5249
  • _5250-5499
  • _5500-5749
  • _5750-5999

我正在寻找一个可以将这些7z文件拖到其中的批处理文件,它将读取文件名的前四个数字,并将其复制到我们NAS上的相应文件夹中。

因此,例如文件:

  • 5476宝马把手-A.7z
  • 5487雪佛兰-Imp.7z

将复制到

\\ nas01 \\ archive \\ _5000-5999 \\ _5250-5499

等等

我弄乱的主要代码是这样的:

@echo off 
for /f "delims=" %%i in ('dir /b /a-d *.7z') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename1:~0,4!"
mkdir "!folder1!" 2>nul
copy "!filename1!" "!folder1!" >nul
)

这行对我不起作用的是:

set "folder1=!filename1:~0,4!"

如何创建某种变量来检查文件名,如有必要,创建文件夹并将其复制到正确的文件夹中? 我将不胜感激!

-Dustin

多亏了评论员的帮助,我才得以弄清楚。 我在如何构造脚本方面遇到问题,但是我明白了!

@echo off
for /f "delims=" %%i in ('dir /b /a-d *.7z') do (
set "filename=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename:~0,4!"
set "subfolder1=_!folder1:~0,1!000-!folder1:~0,1!999"
set "firstdigit=!filename:~0,1!"
set "parent=\\nas01\The_Archives"

REM CONDITIONAL STATEMENTS
IF !folder1! GEQ !firstdigit!000 IF !folder1! LEQ !firstdigit!249 SET "subfolder2=_!firstdigit!000-!firstdigit!249"
IF !folder1! GEQ !firstdigit!250 IF !folder1! LEQ !firstdigit!499 SET "subfolder2=_!firstdigit!250-!firstdigit!499"
IF !folder1! GEQ !firstdigit!500 IF !folder1! LEQ !firstdigit!749 SET "subfolder2=_!firstdigit!500-!firstdigit!749"
IF !folder1! GEQ !firstdigit!750 IF !folder1! LEQ !firstdigit!999 SET "subfolder2=_!firstdigit!750-!firstdigit!999"

mkdir "!parent!\!subfolder1!\!subfolder2!" 2>nul
copy "!filename!" "!parent!\!subfolder1!\!subfolder2!" >nul
)

我今天了解了有关Batch的更多信息,所以这是度过了愉快的一天!

有什么方法可以使我到这里,只需单击文件并将其拖动到此批处理脚本中,而不是获取文件夹中的所有7z文件?

这是此任务的完整批处理代码,主要使用算术表达式和字符串连接来确定源文件夹中每个* .7z文件的目标文件夹路径,或者通过名称将每个文件的名称通过参数传递给批处理文件。

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Source path is the directory of the batch file ending with a backslash.
set "SourcePath=%~dp0"
rem Target path is a UNC path also ending with a backslash.
set "TargetPath=\\nas01\archive\"

rem Run subroutine ProcessFile for each *.7z file in source folder
rem if not at least 1 file was specified on command line to process.
rem Otherwise process the files of which names are passed as arguments
rem to this batch file on starting it. 
if "%~1" == "" (
    for %%I in ("%SourcePath%*.7z") do call :ProcessFile "%%I"
) else (
    for %%I in (%*) do call :ProcessFile "%%~I"
)

rem Restore previous environment and exit this batch file.
endlocal
goto :EOF


rem The subroutine ProcessFile determines the target folders based on
rem first part of the file name separated with one or more spaces from
rem rest of the file name which should be a positive integer number.

rem File names not starting with a valid number are copied (or moved)
rem to the folder _0000-0249\_0000-0249 in specified target folder.

rem For file numbers less than 1000 an extra code is added to copy (or move)
rem those files into folders also having at least 4 digit numbers in name.

:ProcessFile
for /F %%J in ("%~n1") do set "FileNumber=%%J"
set /A FolderNumber1=(FileNumber / 1000) * 1000
set /A FolderNumber2=FolderNumber1 + 999

set /A FolderNumber3=FileNumber - FolderNumber1
if %FolderNumber3% LSS 250 (
    set "FolderNumber3=%FolderNumber1%"
    set /A FolderNumber4=FolderNumber1 + 249
    goto BuildFolderPath
)
if %FolderNumber3% LSS 500 (
    set /A FolderNumber3=FolderNumber1 + 250
    set /A FolderNumber4=FolderNumber1 + 499
    goto BuildFolderPath
)
if %FolderNumber3% LSS 750 (
    set /A FolderNumber3=FolderNumber1 + 500
    set /A FolderNumber4=FolderNumber1 + 749
    goto BuildFolderPath
)
set /A FolderNumber3=FolderNumber1 + 750
set "FolderNumber4=%FolderNumber2%"

:BuildFolderPath
if %FolderNumber1% == 0 (
    set "FolderNumber1=0000"
    set "FolderNumber2=0%FolderNumber2%"
    set "FolderNumber4=0%FolderNumber4%"
    if %FolderNumber3% == 0 (
        set "FolderNumber3=0000"
    ) else (
        set "FolderNumber3=0%FolderNumber3%"
    )
)
set "TargetFolder=%TargetPath%_%FolderNumber1%-%FolderNumber2%\_%FolderNumber3%-%FolderNumber4%"

mkdir "%TargetFolder%" 2>nul
copy /Y "%~1" "%TargetFolder%\" >nul
rem move /Y "%~1" "%TargetFolder%\" >nul
goto :EOF

使用子例程代替了FOR循环中的所有操作,因为可以在子例程中使用GOTO ,这使任务编写起来容易得多。 并且,使用子例程无需使用延迟的环境变量扩展,这对于* .7z文件包含感叹号的情况很有帮助。

此解决方案的主要优点:它可以处理文件名中介于0到2147482999之间的数字。

为了了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • call /?
  • copy /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • mkdir /?
  • move /?
  • rem /?
  • setlocal /?

另请阅读有关使用命令重定向操作符的Microsoft文章,其中解释了>nul2>nul用于将成功和错误消息重定向到设备NUL来抑制它们。

暂无
暂无

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

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