Batch file 将视频文件从图片目录移动到视频目录

Batch file 将视频文件从图片目录移动到视频目录,batch-file,xcopy,robocopy,batch-rename,Batch File,Xcopy,Robocopy,Batch Rename,我的照片导入工具(Picasa)在从手机和相机导入照片和视频方面做得很好。我喜欢的是它根据每张照片/视频的拍摄日期在图片目录下创建一个子文件夹。因此,您最终会得到以下结构: 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 请注意,日期子文件夹可能存在,也可能不存在于C:\Videos下 此外,由于

我的照片导入工具(Picasa)在从手机和相机导入照片和视频方面做得很好。我喜欢的是它根据每张照片/视频的拍摄日期在图片目录下创建一个子文件夹。因此,您最终会得到以下结构:

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
请注意,日期子文件夹可能存在,也可能不存在于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
)
@echo关闭
setlocal EnableExtensions DisableDelayedExpansion
rem定义包含永不删除图片的文件夹。
设置“PicturesFolder=D:\Users\Chad\PicturesTest”
rem获取源目录的字符串长度,以便以后在子字符串类型函数中使用
调用:strlen PicturesFolderDirectoryLength PicturesFolder
echo PicturesFolderDirectoryLength=%PicturesFolderDirectoryLength%
rem将当前目录更改为包含图片的目录。
cd/D“%PicturesFolder%”
rem在此目录中递归搜索具有
rem文件扩展名AVI、MOV、MP4或MPG,并移动这些文件。
对于/F“delims=“%%I in('dir/A-D/B/S*.avi*.mov*.mp4*.mpg 2^>nul'),请调用:MoveVideo“%%I”
rem放弃此批处理代码中定义的所有环境变量
rem并在退出批处理文件之前还原初始当前目录。
端部
后藤:EOF
rem MoveVideo是一个名为current的子程序
rem视频文件名,具有上面FOR循环的完整路径。
rem它首先根据源路径定义视频文件的目标路径
通过删除结尾处的反斜杠并将C:\视频与
rem源路径忽略前11个字符,即C:\Pictures。
rem然后通过重定向
rem错误消息由命令MD输出,用于在以下情况下处理STDERR
rem目标目录已存在于设备NUL以抑制它。
rem下一步,视频文件以静默方式从源文件夹移动到目标文件夹
rem覆盖目标文件夹中已存在的同名文件
rem,因为使用选项/Y。如果视频文件
rem应保存在图片文件夹中,并在中显示错误消息
rem目标文件夹中已存在同名视频文件的情况。
rem Last如果源文件夹完全为空,则会将其删除,这意味着
rem它不包含任何文件或子文件夹。所有父文件夹直到
如果每个父文件夹也为空,rem图片文件夹也将被删除
删除空文件夹后的rem。
rem子例程将退出goto:EOF并执行批处理文件
rem继续在上面的主FOR循环中查找下一个视频文件。
:移动视频
设置“SourcePath=%~dp1”
设置“SourcePath=%SourcePath:~0,-1%”
回显源路径=%SourcePath%
调用集“SourceSubFolder=%%SourcePath:~%PicturesFolderDirectoryLength%%”
回显SourceSubFolder=%SourceSubFolder%
设置“TargetPath=D:\Users\Chad\VideosTest%SourceSubFolder%”
echo TargetPath=%TargetPath%
md“%TargetPath%”2>nul
移动/Y“%~1”“%TargetPath%\%~nx1”>nul
:DeleteSourceFolder
rd“%SourcePath%”2>nul
如果错误级别1转到:EOF
对于/F“delims=“%”中的%%D(“%SourcePath%”),请设置“SourcePath=%%~dpD”
设置“SourcePath=%SourcePath:~0,-1%”
如果/I不是“%SourcePath%”,则=“%PicturesFolder%”转到DeleteSourceFolder
后藤:EOF
:斯特伦
(   
setlocal EnableDelayedExpansion
设置“s=!%~2!#”
设置“len=0”
对于%%P in(4096 2048 1024 512 256 128 64 32 16 8 4 2 1),请执行以下操作(
如果“!s:~%%P,1!”NEQ”“(
设置/a“len+=%%P”
集合“s=!s:~%%P!”
)
)
)
( 
端部
设置“%~1=%len%”
退出/b
)
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
设置“sourcedir=U:\sourcedir”
设置“destdir=U:\destdir”
XCOPY/T“%sourcedir%”“%destdir%”
对于%%x英寸(mp4 mov)DO(
对于/f“tokens=1*delims=>”%%a IN(
“XCOPY/Y/s/d/F/L”%sourcedir%\*.%%x”“%destdir%”
)如果“%%b”neq”,则执行此操作(
设置“topart=%%b”
设置“frompart=%%a”
回音(移动/y“!起始部分:~0,-2!”!起始部分:~1!”
)
)    
后藤:EOF
您需要更改
sourcedir
destdir
的设置以适应您的环境

所需的移动命令仅用于测试。
ECHO
在验证命令正确后,更改
ECHO(MOVE
MOVE
以实际移动文件。追加
>nul
以抑制报告消息(例如
1个文件已移动

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

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

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

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
设置“sourcedir=U:\sourcedir”
设置“destdir=U:\destdir
@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
)
@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