ForFiles批量移动并使用时间戳重命名文件

问题描述 投票:0回答:1

我每小时/每天创建一堆* .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 @[email protected]"
forfiles /p c:\video\ /s /m *.jpg /c "cmd /c echo @[email protected]"

但是当我用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不允许的内容?

windows batch-file cmd
1个回答
1
投票

已解释的问题

首先,仅将echo替换为moveren不会起作用,因为它只会检测传递给它的一个参数。这可以解释语法错误。

renMicrosoft Docs的语法

ren [<Drive>:][<Path>]<FileName1> <FileName2>

rename [<Drive>:][<Path>]<FileName1> <FileName2>

moveMicrosoft Docs的语法

move [{/y | /-y}] [<Source>] [<Target>]

第二,变量@FDATE@FTIME与语言环境有关。它们的格式取决于您设备的区域格式,例如@FDATE的格式可以包含/,而@FTIME的格式可以包含:。这些是保留字符,如果使用不当,可能会导致错误。这可以解释路径错误。


使用forfiles的解决方案

如果要使用forfiles执行此操作,则必须使用for命令,例如this。您可以通过提取子字符串来更改日期格式,例如this answer。您可以通过用点号:代替冒号.来更改时间格式,说明here

[。jpg可以再次使用/m ,. mp4可以再次使用,但也可以像this for loop一样尝试。这意味着您必须将示例中的for嵌套在另一个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,则在我的示例中子字符串的索引不正确。


使用PowerShell的解决方案

。NET Framework的2020/02/10属性与语言环境无关,因为它不依赖于设备的区域格式。如果您更喜欢使用UTC,则还有一个LastWriteTime属性。不过,您仍然必须在批处理文件中使用LastWriteTime循环。

PowerShell的LastWriteTimeUtc返回由LastWriteTimeUtc参数指定的父文件夹的所有子文件夹,使用for参数可以递归地执行此操作。如果您希望结果仅包含.jpg和.mp4文件,则应使用Get-ChildItem。通常,在使用Get-ChildItem时,您需要在路径上附加-Path,但是由于使用了-Recurse,因此没有必要。

使用-Include *.jpg, *.mp4-Include参数,您可以列出\*-RecurseGet-ItemProperty属性。为了使Get-ItemProperty循环更具可读性,必须像-Name这样调用它们并将其串联。必须使用FullnameLastWriteTime转换为字符串并更改其格式。

示例:

Extension

注意:您可以省略for,但是第一个参数必须是路径。

© www.soinside.com 2019 - 2024. All rights reserved.