将视频文件从图片目录移至视频目录

问题描述:

我的照片导入工具(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 

唯一的问题是它把视频放在这个相同的结构下图片。

因此,我想要一个批处理脚本来查找并将所有视频文件(.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:\影片。

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

还喜欢使用RoboCopy,xcopy或xxcopy,因为我拥有它们并在我的机器上今天使用它们。如果使用PowerShell脚本更容易,我可以知道如果它很容易做到。

最终解决 我用渔业部的回答,但增强它只是有点添加一个函数来计算目录字符串长度

@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 
) 
+0

我很尴尬地问这个用户,有近2,000代表,但是...你能告诉我们你到目前为止尝试过吗? – SomethingDark

这是一个注释的批处理代码文件移动任务与保持目录结构。

@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 /?

阅读也是微软的文章关于Using Command Redirection Operators>nul2>nul的解释。在主FOR循环重定向操作符>转义与脱字符^被解释为文字字符上解析FOR命令行和后来由FORDIR执行命令行的重定向操作符。

+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 

你需要改变的sourcedir的设置和destdir以适应您的情况。

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

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

%%x循环分配%%x到所需的扩展。内部xcopy的输出将采用fullsourcefilename -> fulldestinationfilename的形式,因此需要使用>作为分隔符(从文件名到%%a,以文件名到%%b)解析。如果%%b没有设置,那么这是xcopy的报告(复制了n个文件)的最后一行,需要忽略。 tofrom文件名需要删除不需要的,但幸运的是恒定的字符串。

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

+0

在__XCOPY__命令的两行上,目标路径应该是'“%destdir%\”'在末尾带一个反斜杠,以使__XCOPY__清楚该目标是一个目录而不是一个文件,以避免被问到目标是否是一个文件或一个目录。在这种情况下,也可以使用__XCOPY__选项'/ I'来避免询问目标是文件还是目录。但'/ I'只适用于复制多个文件,而目标结尾的反斜杠也适用于复制单个文件。 – Mofi

+0

使用__XCOPY__将单个(隐藏)文件复制到目标文件夹中具有不同名称的目标文件夹(尚不存在)时,无法避免该提示。我在[BATCH文件要求提供文件或文件夹](http://stackoverflow.com/a/35829012/3074564)中发布了针对此特殊问题的解决方案,因为提示符是语言相关的,并且如果批处理文件应该回答自动提示语言独立。 – Mofi

+0

@mofi:第一个xcopy,授予。第二个 - 不,因为它已经作为一个目录存在。自第一个'xcopy'创建目标以来,目标目录就会存在。似乎(我的解释)'xcopy'的'y'开关不起作用。我想我应该提到M $,但是让它固定下来的机会 - 好吧,我会首先通过玩彩票成为亿万富翁... – Magoo