开发者

How can I copy a statically named file to another location with increasing numerical suffixes?

开发者 https://www.devze.com 2023-02-27 00:17 出处:网络
I\'ve got three files in a directory that appear via another process: c:\\result\\results-a.txt c:\\result\\results-b.txt

I've got three files in a directory that appear via another process:

c:\result\results-a.txt
c:\result\results-b.txt
c:\result\results-c.txt

Each time they all appear, I'd like to copy them to another directory with an increasing numerical suffix/prefix, once the files are copied they can be deleted. Every time the batch file starts, it can start with the number 0 (it doesn't have to scan the target directory and continue).

Ex. 开发者_开发知识库 The first time the files all appear, the target directory might look like this:

c:\archive\results-a.0000.txt
c:\archive\results-b.0000.txt
c:\archive\results-c.0000.txt

The second time they appear, the target directory would then contain:

c:\archive\results-a.0000.txt
c:\archive\results-b.0000.txt
c:\archive\results-c.0000.txt
c:\archive\results-a.0001.txt
c:\archive\results-b.0001.txt
c:\archive\results-c.0001.txt

And so on. I'm comfortable piecing this together in a BASH enviroment, but my client requires this be done on a Windows NT (Windows 7, actually) machine. Could someone get me started?

[Edit - Answer] Thanks to Joey below, this is what I ended up coding.

@echo off
setlocal enabledelayedexpansion
set Counter=0

:loop
call :test_file %1\results1.txt
call :test_file %1\results2.txt
call :test_file %1\results3.txt

timeout 2 /nobreak >nul
call :movefiles
timeout 2 /nobreak >nul
goto loop

:test_file
timeout 2 /nobreak >nul
if not exist %1 goto :test_file
goto :eof

:lz
set LZ=000%Counter%
set LZ=%LZ:~-4%
goto :eof

:movefiles
for %%f in (C:\test\*.txt) do (
    call :lz
    move "%%f" "c:\tmp\c-!LZ!-%%~nxf"
)
set /a Counter+=1
goto :eof

A very nice introduction to batch programming. Thanks.


You need a few pieces for this to work.

  1. First of all, a counter:

    set Counter=0
    
  2. Then a subroutine that pads the value with leading zeroes:

    :lz
      set LZ=000%Counter%
      set LZ=%LZ:~-4%
    goto :eof
    

    The %LZ:~-4% is a substring operation that retains the last four characters of the variable value. In this case this is a number, zero-padded to four places.

  3. A loop that checks for files in a certain location:

    :loop
      if exist c:\result\*.txt call :movefiles
      timeout 2 /nobreak >nul
    goto loop
    

    Fairly readable, this one, I guess.

  4. A subroutine that moves the files away:

    :movefiles
      setlocal enabledelayedexpansion
      for %%f in (C:\result\*.txt) do (
        rem Generate the zero-padded number
        call :lz
        move "%%f" "some\target\directory\%%~nf.!LZ!%%~xf"
      )
      endlocal
      rem Increment the counter for next use
      set /a Counter+=1
    goto :eof
    

Piecing all that together leaves you with

@echo off
setlocal enabledelayedexpansion
set Counter=0

:loop
  if exist c:\result\*.txt call :movefiles
  timeout 2 /nobreak >nul
goto loop

:lz
  set LZ=000%Counter%
  set LZ=%LZ:~-4%
goto :eof

:movefiles
  for %%f in (C:\result\*.txt) do (
    call :lz
    move "%%f" "some\target\directory\%%~nf.!LZ!%%~xf"
  )
  set /a Counter+=1
goto :eof

It can be adapted to remember its last value. However, this will only work if the batch file resides in a writable location.

@echo off
setlocal enabledelayedexpansion
set Counter=0
call :init

:loop
  if exist c:\result\*.txt call :movefiles
  timeout 2 /nobreak >nul
goto loop

:lz
  set LZ=000%Counter%
  set LZ=%LZ:~-4%
goto :eof

:movefiles
  for %%f in (C:\result\*.txt) do (
    call :lz
    move "%%f" "some\target\directory\%%~nf.!LZ!%%~xf"
  )
  set /a Counter+=1
  >>%~dpnx0 echo set Counter=%Counter%
goto :eof

:init

Note that the last line (:init) must be terminated with a line break (or better two; I had some issues sometimes with just one in my testing here). This essentially creates a subroutine at the end of the batch file that sets the counter repeatedly until it arrives at its last value.

It isn't exactly fast, though. There will be one set call per counter increment at the end, and all those will be run initially.


Here's something that should get you started. Drop this in a file called incrementName.bat and then run it several times in succession.

@echo off
goto :start
  --------------------------------------------

  incrementName.bat

  shows how to generate a filename with a monotonically
  increasing numeric portion.

  Run this several times in succession to see it in action.

  Mon, 18 Apr 2011  12:51

  --------------------------------------------

:START
setlocal enabledelayedexpansion

call :GETNEXTFILENAME rammalamma.txt
echo Next: %nextname%

@REM copy self to that new name.
copy %0 %nextname%

GOTO END



--------------------------------------------
:GETNEXTFILENAME
@REM this is a subroutine.
@REM %1 is the basename. This logic assumes a 3-character 
@REM filename extension. 
set fname=%1
set ext=%fname:~-3%
set base=%fname:~0,-4%
set idx=0
:toploop1
  @set NUM=00000!idx!
  set nextname=%base%.!NUM:~-5!.%ext%
  if EXIST !nextname! (
    if !idx! GTR 99999 goto:FAIL
    set /a idx=!idx! + 1
    goto:toploop1
  )
)
:Success
goto:EOF
:Fail - overflow
set nextname=%base%.xxxxx.%ext%
goto:EOF
--------------------------------------------


:END
endlocal
0

精彩评论

暂无评论...
验证码 换一张
取 消