I have a bunch of *.mp4 & *.jpg files created on an hourly/daily basis, which use the file structure below:
-- before:
c:\video\2017-10-15\21hour\jpg\12.13.15[M][0@0][0].jpg
c:\video\2017-10-15\21hour\mp4\12.13.01-12.14.32[M][0@0][0].mp4
c:\video\2017-10-18\16hour\jpg\21.42.31[M][0@0][0].jpg
c:\video\2017-10-18\16hour\mp4\21.42.31-21.45.38[M][0@0][0].mp4
I want all the *.jpg & *.mp4 files to get moved to c:\\video\\ & also completely ditch the old name for 'date_time' + extension, similar to below:
-- after:
c:\video\2017-10-15_12.13.15.jpg
c:\video\2017-10-15_12.13.01-12.14.32.mp4
c:\video\2017-10-18_21.42.31.jpg
c:\video\2017-10-18_21.42.31-21.45.38.mp4
I discovered ForFiles, and was able to use the /s to recursively search all subfolders & move the *.mp4 & *.jpg to a single location:
forfiles /p c:\video\ /s /m *.mp4 /c "cmd /c move @PATH c:\video\"
forfiles /p c:\video\ /s /m *.jpg /c "cmd /c move @PATH c:\video\"
Now for the renaming, at this point I can almost taste victory as this gives me the desired filename output:
forfiles /p c:\video\ /s /m *.mp4 /c "cmd /c echo @FDATE_@FTIME.mp4"
forfiles /p c:\video\ /s /m *.jpg /c "cmd /c echo @FDATE_@FTIME.jpg"
But when I replace echo with either ren/rename/move, I get errors: The system cannot find the path specified. The syntax of the command is incorrect.
But the error only happens when I'm using @FDATE and/or @FTIME. These variables all work fine: @FNAME, @ISDIR, @FSIZE
forfiles /p c:\video\ /m *.mp4 /c "cmd /c ren @FILE @ISDIR.@EXT"
forfiles /p c:\video\ /m *.mp4 /c "cmd /c rename @FILE @FSIZE.@EXT"
forfiles /p c:\video\ /m *.mp4 /c "cmd /c move @FILE @EXT.@EXT"
Once I get the renaming part to work, I will combine both the move & rename into one command... But I can't figure out why @FDATE & @FTIME won't take, is there something wrong with my syntax, or is this just something ForFiles doesn't allow?
Firstly, replacing echo
with just move
or ren
alone will not work because it will only detect one argument being passed to it. This could explain the syntax error.
Syntax of
ren
from Microsoft Docsren [<Drive>:][<Path>]<FileName1> <FileName2> rename [<Drive>:][<Path>]<FileName1> <FileName2>
Syntax of
move
from Microsoft Docsmove [{/y | /-y}] [<Source>] [<Target>]
Secondly, the variables @FDATE
and @FTIME
are locale-dependent. Their format will depend on your device's regional formatting, eg @FDATE
's format could contain /
and @FTIME
's format contains :
. These are reserved characters and could result in an error if misused. This could explain the path error.
forfiles
If you want to do this with forfiles
you will have to use the for
command, like this . You can change the date format by extracting substrings like in this answer . You can change the time format by replacing the colon :
with a dot .
, explained here .
You could use /m
once for .jpg and again for .mp4, but you could also try it like this for
loop . This means you would have to nest the for
in the example in another for
loop.
According to the move /?
, if you move just one file you can rename it as well.
setlocal EnableDelayedExpansion
for %%F in (.jpg, .mp4) do (
for /f "tokens=1,2,3,4 delims=|" %%A in (
'forfiles /p "C:\video" /s /m "*%%F" /c "cmd /c echo @PATH^|@EXT^|@FDATE^|@FTIME"'
) do (
set filepath=%%~A
set extension=%%~B
set datestamp=%%~C
set timestamp=%%~D
set parseddate=!datestamp:~6,4!-!datestamp:~3,2!-!datestamp:~0,2!
move "!filepath!" "C:\video\!parseddate!_!timestamp::=.!.!extension!"
)
)
endlocal
If the file count is large, it will take a little while for batch to finish. forfiles
has to read the files first and the for
loop has to also go through that file list. Also, forfiles
is locale-dependent. If the regional date format of your device is 2020/02/10
then the indices of the substring in my example are not correct.
.NET Framework's LastWriteTime
property is locale-independent, as in it does not dependent on your device's regional formatting. There is also a LastWriteTimeUtc
property if you prefer to use UTC. You will still have to use a for
loop inside a batch file though.
PowerShell's Get-ChildItem
returns all children of the parent folder specified by the -Path
parameter and with the -Recurse
parameter you can do so recursively. If you want the result to include just .jpg and .mp4 files you should use -Include *.jpg, *.mp4
. Normally when using -Include
you would need to append \\*
to the path, but since -Recurse
is used it's not necessary.
With Get-ItemProperty
and the -Name
parameter you can list the Fullname
, LastWriteTime
and Extension
properties. To make it more readable for the for
loop they have to be called like $var.Property
and concatenated. ToString()
must be used to convert LastWriteTime
to string and change its format.
for /f "tokens=1,2 usebackq delims=|" %%A in (
`powershell -Command "& {Get-ChildItem -Path 'C:\video\*' -Recurse -Include *.jpg, *.mp4 | ForEach {Get-ItemProperty -Path $_.FullName -Name FullName, LastWriteTime, Extension} | ForEach {$_.FullName+'|'+$_.LastWriteTime.ToString('yyyy-MM-dd_HH.mm.ss')+$_.Extension}}"`
) do (
move "%%~A" "C:\video\%%~B"
)
Note: You can leave out -Path
, but then the first argument must be the path.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.