将视频文件从Pictures目录移动到Video目录

时间:2017-02-21 04:45:10

标签: batch-file xcopy robocopy batch-rename

我的照片导入工具(Picasa)可以很好地导入手机和相机中的照片和视频。我喜欢的是它根据每张照片/视频的照片拍摄日期在Pictures目录下创建一个子文件夹。所以你最终得到了这个结构:

C:\Pictures\2017-02-01\DSC_0001.jpg
C:\Pictures\2017-02-01\DSC_0002.jpg
C:\Pictures\2017-02-01\DSC_0003.mp4 <--- problem

唯一的问题是它将视频放在图片下的相同结构中。

因此,我想修改批处理脚本以查找并将所有视频文件(.mp4,.avi,.mov)从C:\ Pictures目录移动到C:\ Videos目录,但是还有日期子文件夹.... 即。

Move C:\Pictures\2017-02-01\DSC_0003.mp4 to C:\Videos\2017-02-01\DSC_0003.mp4

请注意,日期子文件夹可能存在于C:\ Videos下,也可能不存在。

此外,由于这些是大型视频文件,并且有很多视频文件,为了速度和磁盘空间利用率,我更喜欢实际执行移动而不是复制然后删除的进程。我几乎没有空间了(重新组织这些文件后,我将归档到NAS)。

我也喜欢使用RoboCopy,xcopy或xxcopy,并在我的机器上使用它们。如果使用PowerShell脚本非常容易,我可以学习如果它很容易做到。

最终解决方案 我使用了Mofi的答案,但只是添加了一个函数来计算目录字符串长度

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Define folder with the pictures which is never deleted.
set "PicturesFolder=D:\Users\Chad\PicturesTest"

rem get string length of source directory to later use in a substring type function
call :strlen PicturesFolderDirectoryLength PicturesFolder
echo PicturesFolderDirectoryLength = %PicturesFolderDirectoryLength%

rem Change the current directory to directory with the pictures.
cd /D "%PicturesFolder%"

rem Search recursive in this directory for video files with
rem file extension AVI, MOV, MP4 or MPG and move those files.
for /F "delims=" %%I in ('dir /A-D /B /S *.avi *.mov *.mp4 *.mpg 2^>nul') do call :MoveVideo "%%I"

rem Discard all environment variables defined in this batch code
rem and restore initial current directory before exiting batch file.
endlocal
goto :EOF

rem MoveVideo is a subroutine called with name of current
rem video file name with full path by the FOR loop above.

rem It first defines target path for video file depending on source path
rem by removing the backslash at end and concatenating C:\Videos with the
rem source path omitting the first 11 characters which is C:\Pictures.

rem Then the target directory structure is created with redirecting the
rem error message output by command MD to handle STDERR in case of the
rem target directory already exists to device NUL to suppress it.

rem Next the video file is moved from source to target folder with silently
rem overwriting an already existing file with same name in target folder
rem because of using option /Y. Remove this option if a video file should
rem be kept in pictures folder and an error message should be displayed in
rem case of a video file with same name already existing in target folder.

rem Last the source folder is removed if it is completely empty which means
rem it does not contain any file or subfolder. All parent folders up to the
rem pictures folder are also removed if each parent folder is also empty
rem after deletion of an empty folder.

rem The subroutine is exited with goto :EOF and execution of batch file
rem continues in main FOR loop above with next found video file.

:MoveVideo
set "SourcePath=%~dp1"
set "SourcePath=%SourcePath:~0,-1%"
ECHO SourcePath=%SourcePath%

CALL SET "SourceSubFolder=%%SourcePath:~%PicturesFolderDirectoryLength%%%"
ECHO SourceSubFolder=%SourceSubFolder%

set "TargetPath=D:\Users\Chad\VideosTest%SourceSubFolder%"
echo TargetPath=%TargetPath%

md "%TargetPath%" 2>nul
move /Y "%~1" "%TargetPath%\%~nx1" >nul

:DeleteSourceFolder
rd "%SourcePath%" 2>nul
if errorlevel 1 goto :EOF
for /F "delims=" %%D in ("%SourcePath%") do set "SourcePath=%%~dpD"
set "SourcePath=%SourcePath:~0,-1%"
if /I not "%SourcePath%" == "%PicturesFolder%" goto DeleteSourceFolder
goto :EOF

:strlen <resultVar> <stringVar>
(   
    setlocal EnableDelayedExpansion
    set "s=!%~2!#"
    set "len=0"
    for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
        if "!s:~%%P,1!" NEQ "" ( 
            set /a "len+=%%P"
            set "s=!s:~%%P!"
        )
    )
)
( 
    endlocal
    set "%~1=%len%"
    exit /b
)

2 个答案:

答案 0 :(得分:2)

以下是此文件移动任务的注释批处理代码,其中包含保留目录结构。

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Define folder with the pictures which is never deleted.
rem Note: ~11 in third line of subroutine MoveVideo must be
rem       replaced by ~length of the folder path defined here.
set "PicturesFolder=C:\Pictures"

rem Change the current directory to directory with the pictures.
cd /D "%PicturesFolder%"

rem Search recursive in this directory for video files with
rem file extension AVI, MOV, MP4 or MPG and move those files.
for /F "delims=" %%I in ('dir /A-D /B /S *.avi *.mov *.mp4 *.mpg 2^>nul') do call :MoveVideo "%%I"

rem Discard all environment variables defined in this batch code
rem and restore initial current directory before exiting batch file.
endlocal
goto :EOF

rem MoveVideo is a subroutine called with name of current
rem video file name with full path by the FOR loop above.

rem It first defines target path for video file depending on source path
rem by removing the backslash at end and concatenating C:\Videos with the
rem source path omitting the first 11 characters which is C:\Pictures.

rem Then the target directory structure is created with redirecting the
rem error message output by command MD to handle STDERR in case of the
rem target directory already exists to device NUL to suppress it.

rem Next the video file is moved from source to target folder with silently
rem overwriting an already existing file with same name in target folder
rem because of using option /Y. Remove this option if a video file should
rem be kept in pictures folder and an error message should be displayed in
rem case of a video file with same name already existing in target folder.

rem Last the source folder is removed if it is completely empty which means
rem it does not contain any file or subfolder. All parent folders up to the
rem pictures folder are also removed if each parent folder is also empty
rem after deletion of an empty folder.

rem The subroutine is exited with goto :EOF and execution of batch file
rem continues in main FOR loop above with next found video file.

:MoveVideo
set "SourcePath=%~dp1"
set "SourcePath=%SourcePath:~0,-1%"
set "TargetPath=C:\Videos%SourcePath:~11%"
md "%TargetPath%" 2>nul
move /Y "%~1" "%TargetPath%\%~nx1" >nul

:DeleteSourceFolder
rd "%SourcePath%" 2>nul
if errorlevel 1 goto :EOF
for /F "delims=" %%D in ("%SourcePath%") do set "SourcePath=%%~dpD"
set "SourcePath=%SourcePath:~0,-1%"
if /I not "%SourcePath%" == "%PicturesFolder%" goto DeleteSourceFolder
goto :EOF

此批处理文件还会移除C:\Pictures中移动视频文件后变空的所有文件夹。但它不会删除启动批处理文件时已经为空的文件夹。

要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

  • cd /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • move /?
  • rd /?
  • rem /?
  • set /?
  • setlocal /?

另请阅读Microsoft有关Using Command Redirection Operators的文章,了解>nul2>nul的说明。在主 FOR 循环中,重定向运算符>将使用插入符^进行转义,以在解析 FOR 命令行时解释为文字字符作为 FOR 执行DIR命令行时的重定向运算符。

答案 1 :(得分:0)

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
XCOPY /T "%sourcedir%" "%destdir%"
FOR %%x IN (mp4 mov) DO (
 FOR /f "tokens=1*delims=>" %%a IN (
  'XCOPY /Y /s /d /F /L "%sourcedir%\*.%%x" "%destdir%"'
 ) DO IF "%%b" neq "" (
  SET "topart=%%b"
  SET "frompart=%%a"
  ECHO(MOVE /y "!frompart:~0,-2!" "!topart:~1!"
 )
)    


GOTO :EOF

您需要更改sourcedirdestdir的设置以适合您的具体情况。

为了测试目的,所需的MOVE命令仅为ECHO在您确认命令正确后,将ECHO(MOVE更改为MOVE以实际移动文件。附加>nul以取消报告消息(例如1 file moved

第一个xcopy创建所需的子树,第二个使用/L选项列出而不是复制文件

%%x上的循环将%%x分配给所需的扩展名。内部xcopy的输出将采用fullsourcefilename -> fulldestinationfilename形式,因此需要使用>作为分隔符进行解析,从文件名到%%a,到 - 文件名到%%b。如果未设置%%b,则这是xcopy报告的最后一行(n个文件已复制),需要忽略。 tofrom文件名需要修剪不需要的,但幸运的是常量字符串。

有趣的是,在目标文件名已经存在的情况下,似乎无法使用xcopy来抑制提示。