批处理文件以将文件从文件夹内的特定子文件夹复制到目标文件夹

时间:2019-09-10 06:23:38

标签: batch-file cmd

我有一个像他一样的文件夹结构

folder1-------|
              |123456------123.txt
                          abc.txt
              |234567------fgt.txt
                           234.txt
              |abc---------ytr.txt
                           1234.txt

如果子文件夹的长度为6(仅数字),则需要从主文件夹子目录复制文件。因此,将复制123456,234567中的.txt文件,而不会复制abc。

我尝试使用通配符,但尚未成功。预先感谢。

>xcopy /s "C:\Users\xxx.xxx\Desktop\folder1\*\*.txt" "C:\Users\xxx.xxx\Documents\New folder" /l /D:09-09-2019

3 个答案:

答案 0 :(得分:1)

好的,这是一个例子:

@echo off
setlocal enabledelayedexpansion

for /f %%i in ('dir "C:\Users\xxx.xxx\Desktop\folder1\" /b /ad') do (
  set "str=#%%i"
  set "len=0"
  for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
    if "!str:~%%a,1!" neq "" (
       set /a "len+=%%a"
       set "str=!str:~%%a!"
       if !len! equ 6 if 1%%i equ +1%%i echo %%i is !len! characters   
     )
   )
)

这将对您提供的路径中的目录进行dir。然后它将测试字符串的长度,如果长度为6个字符,它将测试字符串是否为数字,如果为true,它将echo字符串(文件夹名称)及其长度。然后,应按原样进行测试,如果它提供了所需的输出,则可以用复制字符串替换echo部分。

所以您的最终解决方案将是:

@echo off
setlocal enabledelayedexpansion
set /p "mydate=Enter Date (format dd-mm-yyyy): "
for /f %%i in ('dir "C:\Users\xxx.xxx\Desktop\folder1\" /b /ad') do (
  set "str=#%%i"
  set "len=0"
  for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
    if "!str:~%%a,1!" neq "" (
       set /a "len+=%%a"
       set "str=!str:~%%a!"
       if !len! equ 6 if 1%%i equ +1%%i xcopy "C:\Users\xxx.xxx\Desktop\folder1\%%i\*.txt" "C:\Users\xxx.xxx\Documents\New folder" /D:!mydate! 
     )
   )
)

答案 1 :(得分:1)

您可以使用FindStr来隔离与您的模式匹配的目录:

@Echo Off
Set "SrcDir=%UserProfile%\Desktop\folder1"
Set "DstDir=%UserProfile%\Desktop\New folder"
For /F Delims^=^ EOL^= %%A In ('
    "Dir /B/AD "%SrcDir%\*" 2>NUL|FindStr "^[0-9][0-9][0-9][0-9][0-9][0-9]$""
')Do XCopy "%SrcDir%\%%A\*.txt" "%DstDir%\" /D:09-09-2019 /Y>NUL 2>&1

只需修改第="行上的 2 3 之间的路径即可实际的源目录和目标目录。

答案 2 :(得分:1)

这是实现您想要的目标的另一种方法(请参阅所有rem说明):

@echo off
rem // Use a `for /D` loop to iterate through all immediate sub-directories in the given root directory:
for /D %%I in ("%UserProfile%\Desktop\folder1\*") do (
    rem // Store path and name of currently iterated directory in variables:
    set "DIRECTORY=%%~I" & set "NAME=%%~nxI"
    rem // Toggle delayed expansion to be able to write and to read a variable within the same block of code:
    setlocal EnableDelayedExpansion
    rem // Check if directory name holds more than 5 characters:
    if not "!NAME:~5!" == "" (
        rem // Check if directory name holds not more than 6 characters:
        if "!NAME:~0,6!" == "!NAME!" (
            rem // The directory name is exactly 6 characters long.
            rem // Check whether the directory name consists of decimal figures by (mis-)using a `for /F` loop:
            set "FLAG=" & for /F "tokens=1 delims=0123456789 eol=0" %%J in ("!NAME!") do set "FLAG=#"
            rem // The flag variable has not been set, hence the directory name consists of decimal figures:
            if not defined FLAG (
                rem // Do the actual copy job at this point:
                xcopy /I /Y /D:09-09-2019 "!DIRECTORY!\*.txt" "!UserProfile!\Documents\New Folder"
            )
        )
    )
    endlocal
)

您不仅试图在路径的最后一个元素中使用wildcards(在Windows中无法使用),还可以使用for /D loop来解析上一级目录中的通配符,如脚本所示。

该脚本使用~-modifiers(对于for元变量(如%%I和参数引用如%1来说都是相同的)获取当前的纯名称迭代目录:%%~nxI

要确定目录名称是否正好是六(6)个字符长,请应用sub-string expansion

要确定目录名称是否仅由十进制数字组成,将for /F loop使用(误用):for /F将字符串分成给定分隔符(选项delims );由于所有十进制数字都定义为定界符,因此名为1a2b3c的目录将分为abca被分配给{ {1}}之后,由于%%J,其他部分将被忽略),但是目录名tokens=1不会留下任何内容,因为这是一个仅使用定界符的字符串,在这种情况下,123456循环根本不会迭代。与在for /F循环的主体中设置的类似标志的变量FLAG一起,我们可以确定循环是否重复,从而知道当前目录名称是否仅由十进制数字组成

该脚本在同一代码块中写入变量for /F和从中读取变量,除非启用delayed variable expansion,否则通常无法完成。

您可以使用system environment variable %UserProfile%而不是指定NAME,因此该脚本甚至可以在用户配置文件目录不在默认位置的系统上工作。