2017-02-21 1 views
0

Mon outil d'importation de photos (Picasa) effectue un excellent travail d'importation de photos et de vidéos à partir de mon téléphone et de mon appareil photo. Ce que j'aime, c'est qu'il crée un sous-dossier sous le répertoire Pictures en fonction de la date de prise de photo de chaque photo/vidéo. Donc vous vous retrouvez avec cette structure:Déplacez les fichiers vidéo du répertoire Images vers le répertoire Vidéo

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 

Le seul problème est qu'il place des vidéos dans cette même structure sous Photos. En tant que tel, je voudrais redresser un script batch pour trouver et déplacer tous les fichiers vidéo (.mp4, .avi, .mov) du répertoire C: \ Pictures vers le répertoire C: \ Videos, mais aussi avec le sous-dossier de date .... à savoir

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

Notez que le sous-dossier de date peut ou peut ne pas exister sous C: \ Vidéos. Comme il s'agit de gros fichiers vidéo, et qu'ils sont nombreux, je préférerais un processus qui effectue un déplacement et non une copie puis une suppression, pour des raisons de rapidité et d'utilisation de l'espace disque. presque hors de l'espace (après réorganisation de ces fichiers, je vais archiver sur un NAS).

Préférez également utiliser RoboCopy, xcopy ou xxcopy comme je les ai et utilisez-les aujourd'hui sur ma machine. Si massivement plus facile à l'aide de scripts PowerShell, je peux apprendre que si c'est facile à faire.

Solution finale je la réponse de Mofi, mais amélioré juste un peu d'ajouter une fonction pour calculer la longueur de chaîne de répertoire

@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

Je suis gêné de demander cela à un utilisateur qui a près de 2000 rep mais ... pourriez-vous nous montrer ce que vous avez essayé jusqu'à présent? – SomethingDark

Répondre

2

Voici un code de traitement commenté pour cette tâche de déplacement de fichiers avec maintien de la structure de répertoire.

@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 

Ce fichier de commandes supprime également tous les dossiers C:\Pictures qui sont vides après le déplacement des fichiers vidéo. Mais il ne supprime pas les dossiers qui étaient déjà vides lors du démarrage du fichier batch. Pour comprendre les commandes utilisées et leur fonctionnement, ouvrez une fenêtre d'invite de commande, exécutez les commandes suivantes et lisez attentivement toutes les pages d'aide affichées pour chaque commande.

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

Lire aussi l'article Microsoft à propos Using Command Redirection Operators pour une explication de >nul et 2>nul. Dans la principale boucle FOR l'opérateur de redirection > est échappé avec un caractère caret ^ à être interprété comme caractère littéral sur l'analyse syntaxique POUR ligne de commande et plus tard comme opérateur de redirection sur l'exécution de DIR ligne de commande par POUR.

+0

travaillé comme un charme et une fonctionnalité intéressante pour supprimer les répertoires source vides !!! Plus une excellente documentation de code! J'ai légèrement amélioré votre solution pour avoir une fonction permettant de calculer la longueur du répertoire du dossier source afin de ne pas l'avoir codé en dur au cas où je souhaiterais l'utiliser comme référence pour d'autres tâches plus tard. Voir ma réponse finale mise à jour dans la question originale. –

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 

Vous devez modifier les paramètres de sourcedir et destdir en fonction de vos circonstances.

Les commandes MOVE requises sont simplement ECHO éditées à des fins de test. Après avoir vérifié que les commandes sont correctes, remplacez ECHO(MOVE par MOVE pour déplacer réellement les fichiers. Append >nul pour supprimer les messages du rapport (par exemple. 1 file moved)

Le premier xcopy crée les sous-arbres nécessaires, la seconde utilise l'option /L à la liste plutôt que de copier les fichiers

La boucle sur %%x attribue %%x aux extensions nécessaires . La sortie du xcopy interne sera de la forme fullsourcefilename -> fulldestinationfilename, elle doit donc être analysée en utilisant > en tant que délimiteur, de -fichier à %%a, à -fichier à %%b. Si %%b n'est pas défini, il s'agit de la dernière ligne du rapport de xcopy (n fichiers copiés) qui doit être ignorée. Les noms de fichiers to et from doivent être supprimés des chaînes de caractères indésirables, mais heureusement constantes.

Ce qui est intéressant est qu'il ne semble pas y avoir moyen d'utiliser xcopy pour supprimer l'invite dans le cas où le nom de fichier de destination existe déjà.

+0

Sur les deux lignes avec la commande __COPY__, le chemin cible doit être '"% destdir% \ "' avec une barre oblique inverse à la fin pour indiquer à __XCOPY__ que la cible est un répertoire et non un fichier pour éviter d'être interrogé si la cible est un fichier ou un répertoire. Dans ce cas, l'utilisation de l'option __COPY__ '/ I' éviterait de se demander si la cible est un fichier ou un répertoire. Mais '/ I' ne fonctionne que sur la copie de plusieurs fichiers alors que la barre oblique inversée à la fin de la cible fonctionne aussi sur la copie d'un seul fichier. – Mofi

+0

L'invite ne peut pas être évitée en utilisant __XCOPY__ pour copier un seul fichier (caché) dans un dossier cible (pas encore existant) avec un nom différent dans le dossier cible. J'ai posté à [fichier BATCH demande un fichier ou un dossier] (http://stackoverflow.com/a/35829012/3074564) une solution pour ce problème spécial que l'invite dépend de la langue et a besoin de code supplémentaire si le fichier batch doit répondre à la invite automatiquement indépendant sur la langue. – Mofi

+0

@mofi: Le premier xcopy, accordé. Le second - non, car il existera déjà en tant que répertoire. Le répertoire cible existera depuis que le premier 'xcopy' le crée. Il semble que (mon interprétation de) le commutateur 'y' pour' xcopy' ne fonctionne pas. Je suppose que je devrais mentionner à M $, mais les chances de l'avoir réparé - bien, je serais un milliardaire en jouant à la loterie en premier ... – Magoo