2017-02-21 97 views
0

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

回答

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

閱讀也是微軟的文章關於Using Command Redirection Operators>nul2>nul的解釋。在主FOR循環重定向操作符>轉義與脫字符^被解釋爲文字字符上解析FOR命令行和後來由FORDIR執行命令行的重定向操作符。

+0

工作像一個魅力和很好的功能,以刪除空的源目錄!加上優秀的代碼文檔!我稍微增強了您的解決方案,以便具有計算源文件夾目錄長度的功能,以便在未來需要將其用作其他任務的基準時不使用硬編碼。查看原始問題中更新的最終答案。 –

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