Move and rename files from folder to folder as a .

2019-05-31 02:57发布

问题:

I have spent many hours trying to work this out and no luck.

Scenario: Have multiple different file names, but same extension in a folder. On Windows server 2008 64bit. Want to move them to another folder using a schedule batch job. .bat. During the move I want to rename them to include their last modified date. I am trying to put into this format:

yyyymmddhhmmss-name.zip

I have looked at PowerShell and for commands and just can't work it out.

I found this 3-line piece of code and it worked well on Windows 7 but not on Windows Server 2008!

@echo off
set Date=%date:~10,4%%date:~4,2%%date:~7,2%
move d:\Test\*.zip d:\Test1\*%Date%.zip

On the Server, it could not understand the *%Date%. As soon as I removed the *, it worked. I have tried different variations with quotes etc. but not working. I understand the date is not the solution I am after, but if I can't get this simple line to work it wouldn't matter with the rest.

Oh and the offsets did work so I got the date to appear yyyymmdd. I have avoided PowerShell as I am not good with it and I also looked at VBS. But it's not strong points. Can anyone assist?

I know lots of questions are out there similar but nothing quite matches what I am trying to do.

回答1:

WMIC can be used to get the last modified timestamp to fractional second precision. The first 14 characters give the timestamp in exactly the format you are looking for.

Here is a fast solution that does exactly what you asked:

@echo off
for /f "skip=1 delims=" %%A in (
  'wmic datafile where "drive='d:' and path='\\test\\' and extension='zip'" get lastModified^,name'
) do for /f "tokens=1*" %%B in ("%%A") do (
  set "timestamp=%%B"
  set "file=%%~fC"
  set "fileName=%%~nxC"
  setlocal enableDelayedExpansion
  move "!file!" "d:\test1\!timestamp:~0,14!-!fileName!"
  endlocal
)

The above is finicky if you want to change the requirements. Your WMIC command can take a loooong time if you are not careful, and there are some file masks that simply cannot be emulated with WMIC.

Below is a much slower solution that is very convenient. You pass in the source file mask and destination path as parameters. Assume the script is named "addTimeStamp.bat", then you would use addTimeStamp "d:\test\*.zip" "d:\test1"

@echo off
setlocal disableDelayedExpansion
set "filePath="
if "%~2" neq "" for /f "eol=: delims=" %%F in ("%~2\") do set "filePath=%%~fF"
for %%F in (%1) do (
  set "file=%%~fF"
  set "fileName=%%~nxF"
  setlocal enableDelayedExpansion
  for /f "skip=1" %%A in (
    'wmic datafile where "name='!file:\=\\!'" get lastModified'
  ) do for /f %%A in ("%%A") do (
    set "timestamp=%%A"
    move "!file!" "!filePath!!timestamp:~0,14!-!fileName!
  )
  endlocal
)


回答2:

You can do this through the use of wmic command. This allows you to obtain current date and time without getting affected by regional settings. At the same time it will also help you to rename the zip file as well.

@echo off
SETLOCAL EnableDelayedExpansion

for /f "skip=1 tokens=1-6 delims= " %%a in ('wmic path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') do (
    IF NOT "%%~f"=="" (
        set /a FormattedDate=10000 * %%f + 100 * %%d + %%a
        set /a FormattedTime=%%b * 10000 + %%c * 100 + %%e
    )
)

for /f %%f in ("D:\Test*.zip") DO set filename=%%~nf

move "D:\Test*.zip" "D:\%FormattedDate%%FormattedTime%-%filename%.zip"

Hope this helps.



回答3:

You can use a FOR loop and apply the ~t modifier to the loop variable to access every file's last modify timestamp. You will need to adjust the original timestamp value to the necessary format before actually using it with the MOVE command. Here's an example of how you could do that:

@ECHO OFF
FOR %%I IN ("D:\Test\*.zip") DO (
  SET lmdate=%%~tI
  SETLOCAL EnableDelayedExpansion
  SET lmdate=!lmdate:~6,4!!lmdate:~3,2!!lmdate:~0,2!!lmdate:~11,2!!lmdate:~14,2!
  MOVE "%%I" "D:\Test1\!lmdate!-%%~nxI"
  ENDLOCAL
)

It should be noted that the precision of the timestamp returned by a loop variable with the ~t modifier is limited to minutes, so if you really need that to be seconds, as your post suggests, this may not be a solution for you.

Anyway, this is how the script works.

At every iteration, the %%I loop variable is assigned a file name. The ~t modifier instructs the variable to resolve to the corresponding file's last modify timestamp.

The lmdate variable is first initialised with the timestamp as returned by %%~tI (the first SET lmdate statement) and then the value is rearranged to accommodate to the yyyyMMddHHmm format (the second SET lmdate statement). Note that, since the original timestamp's format depends on the system's locale, you may need to modify that second SET statement to adjust to your particular system. The above script assumes the following format:

dd.MM.yyyy HH:mm

The SETLOCAL EnableDelayedExplansion statement which you can also see above is needed for accessing the actual lmdate value inside the loop body. In case you are not aware, "normal" (%) expansion of environment variables in block commands doesn't work when the value is set and retrieved in the same command block. That's where delayed expansion comes in handy. You first need to enable it, then use a different expansion syntax (!s instead of %).

You can see other modifiers used in the script, namely ~n and ~x (~nx when used together). The former resolves to the file name only (no path or extension) and the latter to the extension only. There are other modifiers as well and they are documented in the FOR command's built-in help (FOR /?).



回答4:

I have made one PowerShell Script to do exactly what you want.

Script :-

$src=""      # Source Path of Files to move
$trg=""      # Destination folder
$a=Get-ChildItem $SRC 
IF($a)
{
    for($i=0; $i -le ($a.Count - 1); $i++)
    {
        $fileName=$a[$i].Name
        $fileNameWithoutExtension=$fileName -replace ".zip", ""
        $dirPath=$a[$i].DirectoryName
        $lastModifiedDate=$a[$i].LastWriteTime
        $LMFDate=($lastModifiedDate).ToString("yyyy-MM-dd-hh-mm-ss");
        $srcFile="$dirPath\$fileName"
        move-Item $srcFile "$trg\$LMFDate-$fileName"
    }
}