我有一堆* .mp4& * .jpg每小时/每天创建的文件,使用下面的文件结构:
-- 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
我想要所有* .jpg& * .mp4文件被移动到c:\ video \&也完全放弃旧名称的日期' date_time' +扩展名,类似于以下内容:
-- 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
我发现了ForFiles,并且能够使用/ s递归搜索所有子文件夹&移动* .mp4& * .jpg到一个位置:
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\"
现在进行重命名,此时我几乎可以尝到胜利,因为这给了我想要的文件名输出:
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"
但是当我用ren / rename / move替换echo时,我得到错误: 该系统找不到指定的路径。 该命令的语法不正确。
但错误只发生在我使用@FDATE和/或@FTIME时。这些变量都可以正常工作:@ 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"
一旦我让重命名部分工作,我将结合移动和放大重命名为一个命令...但我无法弄清楚为什么@FDATE& @FTIME不会接受,我的语法有问题,或者这只是ForFiles不允许的内容?
答案 0 :(得分:1)
首先,仅用echo
或move
替换ren
将不起作用,因为它只会检测传递给它的一个参数。这可以解释语法错误。
Microsoft Docs中
ren
的语法ren [<Drive>:][<Path>]<FileName1> <FileName2> rename [<Drive>:][<Path>]<FileName1> <FileName2>
Microsoft Docs中
move
的语法move [{/y | /-y}] [<Source>] [<Target>]
第二,变量@FDATE
和@FTIME
是与语言环境相关的。它们的格式取决于您设备的区域格式,例如@FDATE
的格式可以包含/
,而@FTIME
的格式可以包含:
。这些是保留字符,如果使用不当,可能会导致错误。这可以解释路径错误。
forfiles
如果要使用forfiles
执行此操作,则必须使用for
命令,例如this。您可以通过提取诸如this answer中的子字符串来更改日期格式。您可以通过用点:
代替冒号.
来更改时间格式,如here所述。
您可以一次将/m
用于.jpg,然后再次用于.mp4,但是您也可以像this for
loop一样使用它。这意味着您必须将示例中的for
嵌套在另一个for
循环中。
根据move /?
,如果仅移动一个文件,则也可以对其重命名。
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
如果文件数量很大,批处理将需要一些时间。 forfiles
必须先读取文件,而for
循环也必须遍历该文件列表。另外,forfiles
是与语言环境相关的。如果您设备的区域日期格式为2020/02/10
,则在我的示例中,子字符串的索引不正确。
.NET Framework的LastWriteTime
属性与语言环境无关,因为它不依赖于设备的区域格式。如果您更喜欢使用UTC,则还有一个LastWriteTimeUtc
属性。不过,您仍然必须在批处理文件中使用for
循环。
PowerShell的Get-ChildItem
返回由-Path
参数指定的父文件夹的所有子文件夹,并且可以通过-Recurse
参数来递归地这样做。如果您希望结果仅包含.jpg和.mp4文件,则应使用-Include *.jpg, *.mp4
。通常,在使用-Include
时,您需要将\*
附加到路径中,但是由于使用了-Recurse
,所以没有必要。
使用Get-ItemProperty
和-Name
参数可以列出Fullname
,LastWriteTime
和Extension
属性。为了使for
循环更具可读性,必须像$var.Property
那样调用它们并将其串联。 ToString()
必须用于将LastWriteTime
转换为字符串并更改其格式。
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"
)
注意:您可以省略-Path
,但是第一个参数必须是路径。