【问题标题】:Batch file to find all images and copy to a folder批处理文件以查找所有图像并复制到文件夹
【发布时间】:2013-01-03 19:01:11
【问题描述】:

甚至不确定这是否可能,但我想我会试一试。

所以这是我的问题。我需要为所有图像搜索多个大硬盘(1TB 及更大)并将它们移动到一个文件夹中。我遇到的问题是,无论我尝试用什么语言写这个,我似乎都找不到答案。我要么希望它与 vbs 或 bat 相关,要么不使用 robocopy 命令。我的一些驱动器都是不同的格式,例如 fat32 和 ntfs。我尝试使用批处理文件的一些脚本的问题是我的文件名太长。所以我需要它做的主要功能是找到图像,复制它们,如果它们存在,用 _001 _002 重命名它们,计算移动了多少文件,然后最后删除它们或将它们移动到单独的文件夹中删除(a在我眼里更安全一点)。任何帮助将不胜感激,因为我对此完全感到困惑。

这是我正在编写但刚刚停止的一个脚本。问题在于它复制了文件,但由于某种原因没有保留扩展名。这是我在网上找到的,稍微修改了一下代码。我对代码非常熟悉,但由于某种原因似乎无法弄清楚这一点。

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set TESTFOLDER=allpictures
md "%TESTFOLDER%"


set /a counter=0
FOR /F "tokens=*" %%i IN ('DIR /S /B /A-D C:\Users\user1\Desktop\*.jpg') DO FOR /F "tokens=*" %%j IN ('DIR /B "%%i"') DO IF EXIST ".\%TESTFOLDER%\%%j" (
        set /a counter=!counter!+1
        echo folder: %TESTFOLDER%
        copy "%%i" ".\%TESTFOLDER%\%%j_!counter!"
    ) ELSE copy /B "%%i" ".\%TESTFOLDER%\%%j"
:eof

编辑:下面的VBScript代码

Set fso = CreateObject("Scripting.FileSystemObject")

testfolder = ".\allpictures"
'fso.CreateFolder(testfolder)

CopyFiles fso.GetFolder("E:\")

Sub CopyFiles(fldr)
  For Each f In fldr.Files
    basename  = fso.GetBaseName(f)
    extension = fso.GetExtensionName(f)
    If LCase(extension) = "jpg" Then
      dest  = fso.BuildPath(testfolder, f.Name)
      count = 0
      Do While fso.FileExists(dest)
        count = count + 1
        dest  = fso.BuildPath(testfolder, basename & "_" & count & "." _
          & extension)
      Loop
      f.Copy dest
    End If
  Next

  For Each sf In fldr.SubFolders
    CopyFiles sf
  Next
End Sub

【问题讨论】:

  • 你试过什么?为什么不使用 Perl?我们知道文件的所有扩展名(.jpg、.gif 等)吗?
  • 老实说,从来没有真正想过使用 perl。这对我来说会是更好的选择吗?至于文件扩展名,是的,我正在搜索所有 jpg 扩展名。最终,我想用它来备份以帮助组织我的文件是我的主要目标,以帮助我保持文件井井有条。例如,如果我想在以后搜索 mov 文件。
  • 我在原始问题中添加了我正在处理的代码。
  • 对于我所有的粗暴文件操作,我使用 Perl,它工作得很好而且非常简单。说它对你来说会“更好”是主观的;)。它是一个了不起的主力,非常适合将快速和简单的文件操作放在一起。对于windows,你可以下载Strawberry,它会运行得很好。

标签: batch-file vbscript cmd


【解决方案1】:

你不应该做的事:不要让你被蒙骗

  1. 在您完全理解问题并制定详细的过程计划之前生成代码。 (没有人喜欢“给我一个程序来解决我的问题”类型的问题,有时一个代码 sn-p 可能会澄清一个问题,但要求人们尝试他们承认不能做的事情是很糟糕的教学。)
  2. 从一种新语言开始解决手头的问题(有计划或没有计划)。 (如果您在用母语写情书时遇到困难,那么用外语的语法和词汇来写情书的机会有多大?)

你应该做什么

  1. 考虑您的问题,着眼于最终目标:组织您的图像(如果我正确理解您的评论)。那会是什么样子?当然不是一个文件夹包含数千个名称错误的文件。我会努力以包含 .jpg 且名称不错的文件夹树结束,或者以包含有关我的图片(视频?)和存储路径的合适元信息的数据库,甚至上传到某些云存储。从这个最终目标向后工作:你在上一步中需要什么。

  2. 我假设,第一步是列出所有 .jpg 文件。鉴于您的知识、技能和工具,获取此列表的最简单方法是什么?可能是dir /s [/b] c:\*.jpg > jpglist.txt 的一些变体。对于稍后出现的许多驱动器或其他扩展,您可以将许多这样的行合并到一个 .cmd 文件 (>/>>) 中。此列表和文本编辑器或一些过滤和电子表格可以为您提供有关您的任务的有价值信息:有多少文件?所有尺寸的总和?文件名重复?可能的分类?

  3. 购买新的外置驱动器(您现在知道大小)。这样,您可以在向惊讶的观众展示您精心组织的收藏后将删除推迟到该步骤。 [最后一项任务很简单:只需通过“删除”过滤器脚本输入 jpglist.txt 或使用文本编辑器的搜索和替换功能将 "del /Q " 放在行首。]

  4. 根据您的需要和技能,您可以将基本的 jpglist.txt 转换为具有相关信息的新 .csv 文件,这些文件可以通过电子表格程序手动扫描/检查和/或以编程方式用于生成文件或文件夹名称(附加数字应该是最后的后备)。如果您想要一些 JPG 元数据但不知道如何操作,可以在这里询问(然后甚至显示您用于获取这些文件的大小或日期的代码)。

  5. 使每个步骤可重复且尽可能无损(例如,在完成之前不要移动或删除无法通过一个命令重新创建的文件)。使用您知道的技术/工具;这绝对排除了“在互联网上找到的代码”);如果你想学习一些新的/更有趣的东西,那就在一个玩具项目中做吧。

【讨论】:

    【解决方案2】:

    为操作系统附带的脚本解释器轻松处理的东西安装新的脚本解释器是大材小用。

    您的脚本不维护扩展名的原因是因为您将计数器变量的内容附加到文件名的末尾,因此foo.jpg 变为 foo.jpg1 计数器值为 1。您必须使用修饰符来避免这种情况:%%~nj 只给你文件的名称(没有路径和扩展名),%%~xj 只是扩展名。此外,您可能不希望所有文件都使用一个计数器,而是每个重复文件名一个计数器。

    @echo off
    
    setlocal EnableDelayedExpansion
    
    set TESTFOLDER=allpictures
    md "%TESTFOLDER%"
    
    for /f "tokens=*" %%i in ('dir /s /b /a-d C:\Users\user1\Desktop\*.jpg') do (
      call :copyfile "%%~i"
    )
    
    goto :eof
    
    :copyfile
    set fname=%~nx1
    set counter=0
    
    if not exist ".\%dest%\!fname!" goto docopy
    
    :recheck
    if exist ".\%dest%\%~n1_!counter!%~x1" (
      set /a counter+=1
      goto recheck
    )
    set fname=%~n1_!counter!%~x1
    
    :docopy
    copy "%~1" ".\%dest%\!fname!"
    
    goto :eof
    
    endlocal
    

    在 VBScript 中你可以这样做:

    Set fso = CreateObject("Scripting.FileSystemObject")
    
    testfolder = ".\allpictures"
    fso.CreateFolder(testfolder)
    
    CopyFiles fso.GetFolder("C:\Users\user1\Desktop")
    
    Sub CopyFiles(fldr)
      For Each f In fldr.Files
        basename  = fso.GetBaseName(f)
        extension = fso.GetExtensionName(f)
        If LCase(extension) = "jpg" Then
          dest  = fso.BuildPath(testfolder, f.Name)
          count = 0
          Do While fso.FileExists(dest)
            count = count + 1
            dest  = fso.BuildPath(testfolder, basename & "_" & count & "." _
              & extension)
          Loop
          f.Copy dest
        End If
      Next
    
      For Each sf In fldr.SubFolders
        CopyFiles sf
      Next
    End Sub
    

    【讨论】:

    • 这实际上效果很好,但现在我遇到了另一个问题。我决定为此使用 vbscript,因为批处理文件仍然出现文件名太长。另外,我认为 vb 的效果要好一些。我现在的问题不是使用 c:\users\etc... 我需要从 E: Drive 和所有子文件夹中提取所有图像,但我遇到了代码问题。我知道代码被编程为抓取文件夹,我需要更改一些非常小的东西才能让它工作,但我不知道 VB 脚本足够好来弄清楚它。有什么建议吗?
    • 设置 fso = CreateObject("Scripting.FileSystemObject") testfolder = ".\allpictures" 'fso.CreateFolder(testfolder) CopyFiles fso.GetFolder("E:\") Sub CopyFiles(fldr) For每个 f In fldr.Folder.Files basename = fso.GetBaseName(f) extension = fso.GetExtensionName(f) If LCase(extension) = "jpg" Then dest = fso.BuildPath(testfolder, f.Name) count = 0 Do while fso.FileExists(dest) count = count + 1 dest = fso.BuildPath(testfolder, basename & "_" & count & "." _ & extension) Loop f.Copy dest End If Next
    • 对于 fldr.SubFolders CopyFiles sf Next End Sub 中的每个 sf
    • @dkrider471:只需将"C:\Users\user1\Desktop" 替换为"E:\" 就可以了。这对你不起作用吗?如果是这样:如何?你会得到什么结果,你期望什么结果,一个与另一个有什么不同?
    • 它说 Line: 9 char 3 Path not found ,这就是我想的只是将其更改为 E:\ 它会工作,但不是出于某种奇怪的原因。我在我的第一篇文章中附上了它的确切输入方式,只是为了准确显示我是如何输入的。
    【解决方案3】:

    如果使用 perl,您可以将给定目录中的所有文件都放在一个数组中。 my @Files = glob '<directory>\*.jpg';

    循环遍历每个文件foreach $file (@Files){ ... }

    每个 .jpg 在循环中将被称为$file。您可以通过以下方式获取文件名 my ($originalfilename) = $file; 并添加您想要的任何扩展名,然后将其复制/移动到您想要的任何其他目录。此外,在该循环中,您可以递增计数器循环或仅获取数组的标量值。

    HERE 上有大量关于 perl 文档和教程的东西在互联网上。如果文件操作很普遍,那么学习一些基本的 perl 是值得的。

    【讨论】:

    • -1 要求人们学习一种新的编程语言来解决手头的问题。
    • @bwtrent:如果我针对 perl 提出的一个争论 Batch 相对于 perl 的某些优势的问题提出 Batch 解决方案,您会怎么想?在我看来,批处理文件解决方案的价值或优点低于任何其他语言解决方案...
    • 我想你是想帮忙。通过提供另一种语言的概念,它可能有助于激励我朝着正确的方向前进。这是我的错误,我向社区道歉。学过的知识。不会再发生了。感谢@Ekkehard.Horner 提供了更多信息和帮助的问题。
    猜你喜欢
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多