【问题标题】:Batch file to copy file from specific sub folder inside a folder to destination folder批处理文件将文件从文件夹内的特定子文件夹复制到目标文件夹
【发布时间】:2019-09-10 06:23:38
【问题描述】:

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

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

如果子文件夹的长度为 6(only numbers),我需要从主文件夹子目录复制文件。所以 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

【问题讨论】:

  • 使用for循环,测试字符串的长度以及是否为数值,如果为真,复制文件。
  • @GerhardBarnard 我对批处理脚本几乎没有经验。这就是我寻求帮助的原因。谢谢
  • 好吧,您发布的代码并没有真正尝试执行您描述的操作,这使得这个问题在这里偏离主题,因为这是一个关于特定编程问题的问答网站,但不是请求代码,也不是教程资源。所以请学习How to Ask 并提供一个minimal reproducible example 你认真的编码尝试。谢谢!
  • @aschipfl 如果我冒犯了你,我很抱歉。我需要帮助,所以我请求了。我能理解你在说什么。我加入才几天,所以我不知道很多事情。对不起
  • 不不,没事,不用道歉;我只是试图解释这个网站是如何工作的,并提供了最重要的帮助文章的链接......

标签: batch-file cmd


【解决方案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个字符,它会测试字符串是否为数字,如果是,它会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! 
     )
   )
)

【讨论】:

  • @ABD,请参阅编辑,我进行了更改以适应可能的八进制字符串,并添加了提示用户输入日期的提示。
【解决方案2】:

您可以使用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

只需修改 23 行上的 =" 之间的路径,以适合您的实际源目录和目标目录。 p>

【讨论】:

  • 我没有使用您提供的解决方案,因此没有回复。它确实在对您提供的代码进行较少或没有更改的情况下工作。我将在具有数万个文件的 unc 路径上工作。如果这有助于加快执行速度,我一定会更新。
  • 我可以询问用户输入的日期并使其动态化吗?
  • 当然可以,但是由于您选择了另一个答案,从技术上讲,这将是另一个问题,所以我不愿意扩展我当前的答案。您可以使用Set /P "DateMask=Please enter your date in the format MM-DD-YYYY: " 请求输入,然后您可以将/D:09-09-2019 替换为/D:%DateMask%。请务必注意,要稳健地执行此操作,因为最终用户可以在输入提示符下输入任何内容或任何内容,您应该在继续执行脚本的其余部分之前对该输入执行验证例程。
【解决方案3】:

这是实现您想要的另一种方法(请参阅所有解释性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 的目录将被拆分为abc 部分(a 被分配给%%J,然后由于tokens=1,其他部分被忽略),但目录名称123456 没有留下任何东西,因为这是一个仅分隔符的字符串,在这种情况下for /F 循环根本不会迭代。连同在for /F 循环体中设置的类似标志的变量FLAG,我们能够确定循环是否迭代,从而知道当前目录名称是否仅包含十进制数字。

脚本在同一代码块中写入和读取变量NAME,这通常无法完成,除非您启用delayed variable expansion

您可以使用system environment variable %UserProfile% 而不是指定C:\Users\xxx.xxx,因此该脚本甚至可以在用户配置文件目录不在默认位置的系统上运行。

【讨论】:

  • 感谢您的详细解释。我从这个帖子中学到了很多东西,并了解 SO 是一个多么棒的社区。​​span>
猜你喜欢
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
相关资源
最近更新 更多