计算多个目录中的文件

时间:2016-12-08 21:00:01

标签: batch-file count

当心,长期积累并解决问题和问题。如果您想先查看完整的问题,请参阅下面的标题。

我有一个我正在编写的批处理文件,用于自动移动特定文件。基本上,我有一个设置,我有两个网络,一个连接到互联网,一个隔离在内部网络上。为了在这两个网络之间移动文件,用户将文件放在服务器上的自己的文件夹中,以便有人可以将这些文件拖到外部驱动器上并将它们物理地移动到另一个网络上的计算机上并将这些文件放在类似的文件夹中没有其他网络。

这是关于文件夹布局和移动Folder Structure and Process的过程的糟糕图片

这是移动文件的批处理文件(相关部分)。此脚本不仅在文件夹之间移动文件,还会生成等待移动的所有文件的日志。

@echo off

rem Copies the contents of the external drive to the "AlreadyMoved" folders
dir /b /s /a:d "\\SERVER\Path\Users\*AlreadyMoved" | for /f "delims=\; tokens=3,4,5*" %%a in ('findstr AlreadyMoved') do @xcopy /i /s /y "E:\%%b" "\\SERVER\Path\%%a\%%b\%%c\"    

set folder="E:\"
cd /d %folder%

IF EXIST "E:\" (
goto :DRIVECLEAN
) ELSE (
echo ERROR: "%folder%" DRIVE NOT CONNECTED!
echo(
echo(
echo PLEASE CONNECT %folder% DRIVE AND TRY AGAIN.
exit /b)

:DRIVECLEAN
set folder="E:\"
rem echo This will wipe the %folder% drive clean!
cd /d %folder%
for /F "delims=" %%i in ('dir /b') do (rmdir "%%i" /s/q || del "%%i" /s/q)

rem gets the current date and time in 24 hr format for the text file name.
set hh=%time:~-11,2%
set /a hh=%hh%+100
set hh=%hh:~1%
set dateseed=%date:~10,4%_%date:~4,2%_%date:~7,2%_%hh%%time:~3,2%

set output="%userprofile%\Desktop\Folder\%dateseed%.txt"

rem creates contents of the log file
echo File Header >> %output%
echo( >> %output%
echo Scanned By: %username% >> %output%
echo Date Scanned: %mydate% >> %output%
echo Time Scanned: %mytime% >> %output%
echo( >> %output%

rem echoes the File Name, Size, and Last Modified date in the log file
for /f "delims=" %%F in (
    'dir /b /s \\SERVER\Path\Users ^| findstr ToBeMoved\'
) do for /f "delims=\; tokens=3,4,5*" %%a in ("%%F") do echo %%b: %%d -- Size: %%~zF bytes -- Last Modified: %%~tF >> %output%

rem copies the contents of the "ToBeMoved" folders to the External Drive
dir /b /s /a:d "\\SERVER\Path\Users\*ToBeMoved" | for /f "delims=\; tokens=3,4,5*" %%a in ('findstr ToBeMoved') do @xcopy /i /s /y "\\SERVER\Path\%%a\%%b\%%c" "E:\%%b\"

pause

所有这些都会产生一个如下所示的日志文件:

File Header 

Scanned By: username
Date Scanned: 12-08-2016 
Time Scanned: 01:03 PM 

Last, First1: FileName1.ext -- 10000 bytes -- Last Modified: 12/08/16 2:50 PM
Last, First1: FileName2.ext -- 10000 bytes -- Last Modified: 12/08/16 2:55 PM
Last, First2: FileName3.ext -- 10000 bytes -- Last Modified: 12/08/16 2:50 PM
Last, First2: FileName4.ext -- 10000 bytes -- Last Modified: 12/08/16 2:55 PM

问题在这里开始!

因此,经过极长的挣扎,这就是问题所在。

我想让文本文件看起来像这样:

File Header

Moved By: username
Date Moved: 12-08-2016 
Time Moved: 01:03 PM 

Last, First1
FileName1.ext -- 9 KB -- Last Modified: 12/08/16 2:50 PM
FileName2.ext -- 9 KB -- Last Modified: 12/08/16 2:55 PM
Total Moved: 2 Files

Last, First2
FileName3.ext -- 9 KB -- Last Modified: 12/08/16 2:50 PM
FileName4.ext -- 9 KB -- Last Modified: 12/08/16 2:55 PM
FileName4.ext -- 9 KB -- Last Modified: 12/08/16 2:56 PM
Total Moved: 3 Files

您会注意到这个和之前的文本文件存在一些差异,但我尝试弄清楚的关键区别在于如何计算特定用户中的文件数量&#39 ; s" ToBeMoved"夹。

我注意到批处理中没有明显的计数功能,但我发现了一些计算目录中文件的方法,但我似乎无法弄清楚如何将这些实现到这个脚本中,它实际上并没有爆炸。

在我看来,显而易见的解决方案是在输出日志文件内容的同一循环中实现计数。否则,我不知道如何将所有用户的信息保存在一起。也就是说,我所拥有的循环已经让我永远地拼凑在一起(我不是批处理专家)而且我还没有找到如何为这些循环添加复杂添加的最微弱的线索。

因为看到的额外奖励(这与这个问题的范围并不完全相关,但如果有人也提供这些问题的帮助,我也不会反对。我&#39 ;我还在研究它们,如果我无法解决这些问题,我可能不得不为它们提出单独的问题。)我需要能够对尺寸值进行一些转换,添加换行符。

有人能想到我能做到这一点吗?或者至少指出我正确的方向?

编辑:这是对elzooilogico的回答。我实现了他建议的更改和执行的代码没有任何错误,但文本文件格式不正确。我把一些测试文件放到一些文件夹中,看看会发生什么。

我应该得到这样的东西:

File Header

Moved By: username
Date Moved: 12-09-2016
Time Moved: 10:30 AM

Last,First1
FileName1.ext -- Size: 1 KB -- Last Modified: 12/09/2016 10:25 AM
FileName2.ext -- Size: 1 KB -- Last Modified: 12/09/2016 09:28 AM 
FileName3.ext -- Size: 1 KB -- Last Modified: 12/09/2016 09:29 AM 
FileName4.ext -- Size: 1 KB -- Last Modified: 12/09/2016 09:31 AM
Total Moved: 4 Files

Last,First2
FileName5.ext -- Size: 1 KB -- Last Modified: 12/09/2016 09:31 AM 
FileName6.ext -- Size: 1 KB -- Last Modified: 12/09/2016 09:37 AM 
FileName7.ext -- Size: 1 KB -- Last Modified: 12/09/2016 09:42 AM
Total Moved: 3 Files

相反它看起来像这样:

File Header

Moved By: username
Date Moved: 12-09-2016
Time Moved: 10:30 AM

Last,First1
Last,First1
Last,First1
Last,First1
Last,First2
Last,First2
Last,First2
FileName1.ext -- Size: 103 bytes -- Last Modified: 12/09/2016 10:25 AM
FileName2.ext -- Size: 463 bytes -- Last Modified: 12/09/2016 09:28 AM 
FileName3.ext -- Size: 463 bytes -- Last Modified: 12/09/2016 09:29 AM 
FileName4.ext -- Size: 531 bytes -- Last Modified: 12/09/2016 09:31 AM 
FileName5.ext -- Size: 531 bytes -- Last Modified: 12/09/2016 09:31 AM 
FileName6.ext -- Size: 527 bytes -- Last Modified: 12/09/2016 09:37 AM 
FileName7.ext -- Size: 527 bytes -- Last Modified: 12/09/2016 09:42 AM

现在有可能我以某种方式错误地实现了它,因为他写的循环肯定高于我的技能水平。但是我将它直接复制到我的代码中并在必要时更正了通用位。

最终编辑:我必须第一次把它弄错了,因为它现在完美无缺!

1 个答案:

答案 0 :(得分:1)

  

未经测试

如果您的批处理逻辑正常,请尝试从rem creates contents of the log file行更改为

rem creates contents of the log file
>>"%output%" (
  echo(File Header
  echo(
  echo(Scanned By: %username%
  echo(Date Scanned: %mydate%
  echo(Time Scanned: %mytime%
  echo(
)

setlocal EnableDelayedExpansion 
set "footer="
set "current="
set/a counter=0

rem echoes the File Name, Size, and Last Modified date in the log file
>>"%output%" (
  for /f "delims=" %%F in (
    'dir /b /s \\SERVER\Path\Users ^| findstr ToBeMoved\'
  ) do (
    for /f "delims=\; tokens=3,4,5*" %%a in ("%%F") do (
      if "!current!" neq "%%b" (
         set "current=%%b"
         if defined footer echo(Total Moved: !counter! Files & echo(
         set/a counter=0, footer=1
         echo(
         echo(%%b
      )
      set/a counter+=1, size=%%~zF, kbSize=size/1024
      echo %%d -- Size: !kbSize! Kb -- Last Modified: %%~tF
    )
  )
  if defined footer echo(Total Moved: !counter! Files
)  
EndLocal

rem copies the contents of the "ToBeMoved" folders to the External Drive
dir /b /s /a:d "\\SERVER\Path\Users\*ToBeMoved" | for /f "delims=\; tokens=3,4,5*" %%a in ('findstr ToBeMoved') do @xcopy /i /s /y "\\SERVER\Path\%%a\%%b\%%c" "E:\%%b\"

pause

请注意

>>"%output%" (
   for ... do (
     echo(...
     echo(...
   )
)  

仅打开文件一次,而

   for ... do (
     echo(...>>"%output%"
     echo(...>>"%output%"
   )

在使用>>"%output%"重定向的任何时候打开和关闭文件,因此第一个加速块。

  

编辑:简要说明

顺便说一句

>>"%output%" (
   for ... do (
     echo(...
     echo(...
   )
)  

相同
(
   for ... do (
     echo(...
     echo(...
   )
)>>"%output%"  
  

说明

首先:如上所述,标题在一个打开 - 关闭循环中回显到输出文件。

  

记住:当命令处理器找到一个块(任何东西之间)   括号),完全解析它并将变量扩展到值   它们在评估块时有。如果更新变量值   在块内,您需要为变量启用延迟扩展   反映所做的改变。关于How does the Windows Command Interpreter (CMD.EXE) parse scripts?

有一个很好的解释

因此,我们使用setlocal EnableDelayedExpansion进入延迟扩展模式,因为我们将使用块内更新的变量,这意味着我们必须将变量扩展语法从%var%更改为!var!延迟扩张工程。

setlocal EnableDelayedExpansion 
set "footer="
set "current="
set/a counter=0

此时fotter and current未定义。这就是set "fotter="set "current="的目的,我们将counter初始化为0。

现在我们准备进入主for循环,

for /f "delims=" %%F in (...) do (
  for /f "delims=\; tokens=3,4,5*" %%a in ("%%F") do (
    if "!current!" neq "%%b" (
      set "current=%%b"
      if defined footer echo(Total Moved: !counter! Files & echo(
      set/a counter=0, footer=1
      echo(
      echo(%%b
    )
    set/a counter+=1, size=%%~zF, kbSize=size/1024
    echo %%d -- Size: !kbSize! Kb -- Last Modified: %%~tF
  )
)
if defined footer echo(Total Moved: !counter! Files

if使用第二个current循环给出的第二个令牌的内容测试for var的内容。该块仅在当前更改时执行,并记住未定义,因此第一次也执行。 每次更改其值时,表示令牌已更改(因此,在这种情况下是文件夹更改)和

  1. 我们更新当前的值
  2. 然后,如果定义footer打印页脚(计数器的内容)。第一次footer未定义,因此不会打印任何页脚。
  3. 然后重置计数器,并定义footer,以便下次打印。
  4. 然后打印文件夹的名称。
  5. if次迭代后执行for块行

    1. 第一行,更新计数器并计算文件大小的Kb大小。
    2. 第二个,将当前操作的信息刷新到输出文件
    3. if defined footer echo(Total Moved: !counter! Files块之后的最后for确保打印最后一个页脚,因为if块将不会在最后for次迭代中执行,留下最后的foder内容而没有页脚

      希望它有所帮助!

        

      新编辑:想想我晚上需要更多咖啡......

      顺便说一句,如果您的比较不是大小写,那么您可以使用if /I "!current!" neq "%%b"代替if "!current!" neq "%%b"(区分大小写)