2 votes

Fichier batch Windows pour lister tous les doublons (et le fichier original) dans l'arbre et les trier

Je dois vérifier dans une arborescence les fichiers en double et les écrire tous dans le fichier List.txt. Mais mon script semble sauter un des emplacements de fichiers dans chaque groupe. (Par exemple, s'il y a 4 fichiers en double, seuls 3 d'entre eux apparaissent dans la liste).

Si je ne me trompe pas, c'est l'emplacement du "previousFile" de la dernière comparaison qui manque. Comment l'écrire aussi dans la liste ?

Par ailleurs, comment puis-je regrouper les chemins dans le fichier List.txt en fonction du nom de fichier de façon à ce que cela ressemble à ceci :

Fichier nomfichierA.txt :
C:\path1\fileNameA.txt
C:\path2\fileNameA.txt
C:\path3\fileNameA.txt

Fichier nomfichierB.txt :
C:\path1\fileNameB.txt
C:\path2\fileNameB.txt
C:\path3\fileNameB.txt
C:\path4\fileNameB.txt

Fichier nomfichierC.txt :
C:\path1\fileNameC.txt
C:\path2\fileNameC.txt

...

?

C'est mon script jusqu'à présent :

@echo off

setlocal disableDelayedExpansion

set root=%1

IF EXIST List.txt del /F List.txt

set "prevTest=none"
set "prevFile=none"

for /f "tokens=1-3 delims=:" %%A in (
  '"(for /r "%root%" %%F in (*) do @echo %%~zF:%%~fF:)|sort"'
) do (
  set "currentTest=%%A"
  set "currentFile=%%B:%%C"
  setlocal enableDelayedExpansion
  set "match="
  if !currentTest! equ !previousTest! fc /b "!previousFile!" "!currentFile!" >nul && set match=1
  if defined match (
    echo File "!currentFile!" >> List.txt
    endlocal
  ) else (
    endlocal
    set "previousTest=%%A"
    set "previousFile=%%B:%%C"
  )
)

1voto

JosefZ Points 15232

Vous devez compter et ajouter echo précédent nom de fichier vers echo actuel un en cas de premier match.

Note '"(for /r "%root%" %%F in (*) do @echo(%%~nxF?%%~zF?%%~fF?)|sort"' changements :

  • usado ? (point d'interrogation) comme délimiteur : caractère réservé par Nommer les fichiers, les chemins et les espaces de noms
  • ajouté %%~nxF? préfixe pour sort La sortie se fait correctement par nom de fichier, même dans ma structure de dossier de test bâclée, voir l'exemple de sortie ci-dessous.

Cette sortie montre que même cmd les caractères vénéneux (comme & , % , ! etc.) dans les noms de fichiers sont traités correctement avec la fonction DisableDelayedExpansion gardé.

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "root=%~1"
if not defined root set "root=%CD%"

set "previousTest="
set "previousFile="
set "previousName="
set "match=0"

for /f "tokens=1-3 delims=?" %%A in (
  '"(for /r "%root%" %%F in (*) do @echo(%%~nxF?%%~zF?%%~fF?x)|sort"'
) do (
    set "currentName=%%A"
    set "currentTest=%%B"
    set "currentFile=%%C"
    Call :CompareFiles
)
ENDLOCAL
goto :eof

:CompareFiles
  if /I "%currentName%" equ "%previousName%" ( set /A "match+=1" ) else ( set "match=0" )
  if %match% GEQ 1 (
      if %match% EQU 1 echo FILE "%previousFile%" %previousTest%
      echo      "%currentFile%" %currentTest%
  ) else (
      set "previousName=%currentName%"
      set "previousTest=%currentTest%"
      set "previousFile=%currentFile%"
  )
goto :eof

Le script ci-dessus liste tous les fichiers dupliqués. noms indépendamment de leur taille et de leur contenu. Exemple de sortie :

FILE "d:\bat\cliPars\cliParser.bat" 1078
     "d:\bat\files\cliparser.bat" 12303
     "d:\bat\Unusual Names\cliparser.bat" 12405
     "d:\bat\cliparser.bat" 335
FILE "d:\bat\Stack33721424\BÄaá^ cčD%OS%Ď%%OS%%(%1!)&°~%%G!^%~2.foo~bar.txt" 120
     "d:\bat\Unusual Names\BÄaá^ cčD%OS%Ď%%OS%%(%1!)&°~%%G!^%~2.foo~bar.txt" 120

Pour répertorier tous les fichiers dupliqués noms avec le même taille mais indépendamment de leur contenu :

:CompareFiles
  REM if /I "%currentName%" equ "%previousName%" (
  if /I "%currentTest%%currentName%" equ "%previousTest%%previousName%" (
      set /A "match+=1"
      REM fc /b "%previousFile%" "%currentFile%" >nul && set /A "match+=1"
  ) else ( set "match=0" )

Pour répertorier tous les fichiers dupliqués noms avec le même taille et binaire contenu :

:CompareFiles
  REM if /I "%currentName%" equ "%previousName%" (
  if /I "%currentTest%%currentName%" equ "%previousTest%%previousName%" (
      REM set /A "match+=1"
      fc /b "%previousFile%" "%currentFile%" >nul && set /A "match+=1"
  ) else ( set "match=0" )

Editar Si le nom du fichier n'a pas d'importance (seulement son contenu), vous pourriez appliquer les prochaines modifications dans FOR et dans :CompareFiles sous-routine :

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "root=%~1"
if not defined root set "root=%CD%"

set "previousTest="
set "previousFile="
set "match=0"

for /f "tokens=1-2 delims=?" %%A in (
  '"(for /r "%root%" %%F in (*) do @echo(%%~zF?%%~fF?)|sort"'
) do (
    set "currentTest=%%A"
    set "currentFile=%%B"
                                     rem optional: skip all files of zero length
    if %%A GTR 0 Call :CompareFiles
)
ENDLOCAL
goto :eof

:CompareFiles
  if /I "%currentTest%" equ "%previousTest%" (
      fc /b "%previousFile%" "%currentFile%" >nul && set /A "match+=1"
  ) else ( set "match=0" )
  if %match% GEQ 1 (
      if %match% EQU 1 echo FILE "%previousFile%" %previousTest%
      echo      "%currentFile%" %currentTest%
  ) else (
      set "previousTest=%currentTest%"
      set "previousFile=%currentFile%"
  )
goto :eof

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X