2017-04-24 2 views
0

Ich versuche, durch ein Verzeichnis zu durchlaufen und pic out das Unterverzeichnis, die in anderen Verzeichnissen begraben werden kann, und ziehen Sie das Verzeichnis, das zuletzt erstellt wurde. Ich habe hier eine Schleife, die in das Root-Verzeichnis, das gesetzt wird, gehen und nur Verzeichnisse betrachten, alle Unterverzeichnisse einbeziehen, sie nach Erstellungsdatum sortieren, und die Schleife am Ende der Liste am meisten setzen lassen neulich, was dann wieder rauskommt. Aus irgendeinem Grund passiert die Sortierung jedoch nicht korrekt. Es zieht ein Verzeichnis heraus, das nicht das letzte ist. Ich kann das Problem nicht genau erkennen. Was könnte das verursachen? Benutze ich die Sortierung richtig? Vergleicht es Unterverzeichnisse nicht mit anderen Verzeichnissen auf anderen Ebenen? Jede Hilfe würde sehr geschätzt werden. Batch-Datei Schleife zeigt nicht neueste Verzeichnis

@ECHO OFF 
SET dir=C:\Users\Darren\Google Drive\ 
echo %dir% 
FOR /F "delims=" %%i IN ('dir "%dir%" /b /s /ad-h /t:c /od') DO (
echo %%i 
SET a=%%i) 
SET sub=%a% 
echo Most recent subfolder: %sub% 
+0

'dir/od' Sortieren in der Reihenfolge des Datums für das aktuelle Verzeichnis, so wird Ihr Code den zuletzt erstellten Verzeichnisnamen im letzten gefundenen Verzeichnis auswählen, nicht die zuletzt erstellten von- Alle Verzeichnisse und Unterverzeichnisse. Sie müssten eine Liste von Verzeichnissen mit dem extrahierten Datum in ein yymmddhhmmss-Format sortieren, wenn Sie den zuletzt erstellten Verzeichnisnamen möchten. Nicht besonders schwer, aber auch keine One-Line. Überlegen Sie, ob Sie das Erstellungsdatum oder das Datum der letzten Aktualisierung benötigen - und warum dieses Verzeichnis? Suchen Sie eigentlich nach der letzten (erstellten) Datei? – Magoo

+0

Das habe ich mir gedacht. Könnte ich nicht einfach eine Liste aller Verzeichnisse erstellen und sie dann nach erstelltem Datum sortieren? Mein Ziel ist es, das zuletzt erstellte Verzeichnis zu ermitteln und eine E-Mail-Benachrichtigung zu senden, wenn mehr als 20 Dateien darin enthalten sind. Ich habe alle anderen Aspekte des Skripts, nur nicht die Sortierung. –

+0

Wenn sie alle im selben Verzeichnis sind, ja. Wenn dies nicht der Fall ist, müssen Sie die Daten vergleichen, indem Sie die Datumszeichenfolge (müssen wissen, welches Format Sie verwenden) in yymm aufspalten. Eine andere Möglichkeit könnte sein, den Verzeichnisbaum in eine Datei zu protokollieren und zu sehen, welche neue Scheinbar - wenn die neuen Verzeichnisse nicht alle ein Elternteil teilen, müssen Sie sie immer noch sortieren, indem Sie die Daten vergleichen. Möchten Sie nicht über alle neuen Verzeichnisse informiert werden, die> 20 Dateien enthalten? Das sollte einfacher zu bauen sein. – Magoo

Antwort

0
@ECHO OFF 
SETLOCAL 
SET "sourcedir=U:\sourcedir" 
SET "filename1=%sourcedir%\q43579378.txt" 
SET "filename2=%sourcedir%\q43579378_2.txt" 
(
FOR /f "delims=" %%a IN (
'dir /b /s /ad "%sourcedir%\*" ' 
) DO ECHO %%~a 
)>"%filename1%" 

IF EXIST "%filename2%" (
FOR /f "delims=" %%a IN ('findstr /L /V /i /x /g:"%filename2%" "%filename1%"') DO (
    FOR /f %%c IN ('dir /b /a-d "%%a\*" 2^>nul^|find /c /v "" ') DO (
    IF %%c gtr 20 ECHO(send email directory %%a has %%c files 
) 
) 
) 

MOVE "%filename1%" "%filename2%" >nul 
GOTO :EOF 

ich verwendet, um ein Testverzeichnis als sourcedir. Natürlich muss es nicht mit dem zu scannenden Verzeichnis identisch sein, und die Dateinamen können beliebig sein.

Die erste for eine Liste der absoluten dirctorynames baut derzeit bestehenden in filename1 (der „Ersatz“ Klammerpaar die for umschließenden ermöglicht die Umleitung)

Wenn filename2 vorhanden ist (die für jeden Lauf nach dem ersten sein), findet dann die Differenz zwischen filename1 und filename2, mit /L wörtlichen, /v nicht /i Groß- und Kleinschreibung /x genaue Übereinstimmung /g: Strings in dieser Datei und weisen Sie jeden neuen Verzeichnisnamen zu %%a entspricht.

scannen dann das Verzeichnis "%%a", nur Dateien, unterdrückt file not found Nachrichten und die Anzahl von zurückgegebenen Zeilen zu zählen (Zählung /c/v Linien nicht "" eine leere String-Matching). Weisen Sie re4sult dem Wert %%c zu, testen Sie, und wählen Sie, wo die Aktion ausgeführt werden soll.

die Carets ^ vor den Redirector in dem Befehl-zu-sein-ausgeführt des for ... %%c Befehl die Umleitungen entkommen, so dass sie als Teil des Befehls-zu-sein-ausgeführt interpretiert werden, nicht die for.

+0

Warum sage ich nicht "dir/b/s/ad"% sourcedir% \ * ">"% filename1% "' anstelle einer 'for/F'-Schleife dafür? – aschipfl

+0

@aschipfl Warum? Weil ich nicht daran gedacht habe. Ja - das würde funktionieren ... – Magoo

0

Der Befehl sortiert den Inhalt jedes Unterverzeichnisses einzeln, und es gibt keine Möglichkeit, dieses Verhalten zu ändern.


Ein möglicher alternativer Ansatz ist den wmic Befehl zu verwenden, die ein wenig langsam, aber fähig ist Ableiten die Datumsinformation (Erstellung, letzte Änderung, die letzte Zugriffs) in einem standardisierten, sortierbare, regions und locale- unabhängiges Format:

wmic FSDir where Name="D:\\Data" get CreationDate /VALUE 
wmic FSDir where (Name="D:\\Data") get CreationDate /VALUE 

unten sind zwei Skripte, so dass eine for /D /R Schleife verwenden, um alle (Unter-) Verzeichnisse zu erhalten, werden die oben wmic Befehlszeilen, for /F ihre Leistung und einen einfachen Befehl erfassen die Sortierung zu tun, indem Alter.


Die erste erstellt eine temporäre Datei, die alle Verzeichnisse zu sammeln, zusammen mit ihrem Erstellungsdatum, in folgendem Format:

20170424215505.000000+060 D:\Data 

Zum Sortieren des sort Befehl verwendet wird. Hier ist der Code:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "_ROOT=%~1" & rem // (use first command line argument as the root directory) 
set "_PATTERN=*" & rem // (search pattern for directories; `*` matches all) 
set "_TMPF=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (specify a temporary file) 

rem // Write list of directory paths preceded by their creation dates to temporary file: 
> "%_TMPF%" (
    set "ERR=0" 
    rem // Enumerate all matching directories recursively: 
    for /D /R "%_ROOT%" %%D in ("%_PATTERN%") do (
     rem // Store currently iterated directory path: 
     set "DIRPATH=%%~D" 
     rem // Toggle delayed expansion to avoid trouble with the exclamation mark: 
     setlocal EnableDelayedExpansion 
     (
      rem /* Capture `wmic` output to query creation date of currently iterated 
      rem directory in locale-dependent and sortable format: */ 
      for /F "tokens=2 delims==" %%L in (' 
       rem/ Do two attempts, because one approach can handle `^)` and one can handle `,`; ^&^
        rem/ note that `wmic` cannot handle paths containing both of these characters: ^&^
        2^> nul wmic FSDir where Name^="!DIRPATH:\=\\!" get CreationDate /VALUE ^|^|^
        2^> nul wmic FSDir where ^(Name^="!DIRPATH:\=\\!"^) get CreationDate /VALUE 
      ') do (
       rem // Do nested loop to avoid Unicode conversion artefacts (`wmic` output): 
       for /F %%K in ("%%L") do echo(%%K !DIRPATH! 
      ) 
     ) || (
      rem // This is only executed in case a path contains both `)` and `,`: 
      >&2 echo ERROR: Could not handle directory "!DIRPATH!"^^! 
      set "ERR=1" 
     ) 
     endlocal 
    ) 
) 
rem /* Return content of temporary file in sorted manner using `sort` command, 
rem remember last item of sorted list; clean up temporary file: */ 
for /F "tokens=1*" %%C in ('sort "%_TMPF%" ^& del "%_TMPF%"') do set "LASTDIR=%%D" 
rem // Return newest directory: 
echo "%LASTDIR%" 

endlocal 
exit /B %ERR% 

Die zweite speichert jedes Verzeichnis in einer Variablen des Erstellungsdatums benannt, in folgendem Format:

$20170424215505.000000+060=D:\Data 

Für Sortierung, die set Befehl wird verwendet. Hier ist der Code:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "_ROOT=%~1" & rem // (use first command line argument as the root directory) 
set "_PATTERN=*" & rem // (search pattern for directories; `*` matches all) 

set "ERR=0" 
rem // Clean up variables beginning with `$`: 
for /F "delims==" %%C in ('2^> nul set "$"') do set "%%C=" 
rem // Enumerate all matching directories recursively: 
for /D /R "%_ROOT%" %%D in ("%_PATTERN%") do (
    rem // Store currently iterated directory path: 
    set "DIRPATH=%%~D" 
    rem // Toggle delayed expansion to avoid trouble with the exclamation mark: 
    setlocal EnableDelayedExpansion 
    (
     rem /* Capture `wmic` output to query creation date of currently iterated 
     rem directory in locale-dependent and sortable format: */ 
     for /F "tokens=2 delims==" %%L in (' 
      rem/ Do two attempts, because one approach can handle `^)` and one can handle `,`; ^&^
       rem/ note that `wmic` cannot handle paths containing both of these characters: ^&^
       2^> nul wmic FSDir where Name^="!DIRPATH:\=\\!" get CreationDate /VALUE ^|^|^
       2^> nul wmic FSDir where ^(Name^="!DIRPATH:\=\\!"^) get CreationDate /VALUE 
     ') do (
      rem // Do nested loop to avoid Unicode conversion artefacts (`wmic` output): 
      for /F %%K in ("%%L") do (
       rem /* Assign currently iterated path to variable named of the 
       rem respective creation date preceded by `$`: */ 
       endlocal & set "$%%K=%%~D" 
      ) 
     ) 
    ) || (
     endlocal 
     rem // This is only executed in case a path contains both `)` and `,`: 
     >&2 echo ERROR: Could not handle directory "%%~D"! 
     set "ERR=1" 
    ) 
) 
rem /* Return all variables beginning with `$` in sorted manner using `set` command, 
rem remember last item of sorted list: */ 
for /F "tokens=1* delims==" %%C in ('2^> nul set "$"') do set "LASTDIR=%%D" 
rem // Return newest directory: 
echo "%LASTDIR%" 

endlocal 
exit /B %ERR% 
Verwandte Themen