cmd-Batch: neuste Datei einer Dateimenge exkl. einer Untermenge daraus?


14.11.2022, 12:03

Ich habe meine Anforderung nun anders lösen können. Darum brauche ich für die obige Idee keinen Batch mehr.

Grüsse, Louis

1 Antwort

@echo off
chcp 65001 >nul
 rem erzeuge Array mit dem verglichen werden  soll.
 rem ermittle alle .wav-Dateien nach Erzeugungsdatum sortiert die Neueste zuerst!
for /f "tokens=1* delims=[]" %%a in ('dir /tc /o-d /b "*.wav" ^| find /v /n ""') do (
  set "WavArray.%%a=%%b"
)




:check
echo Drücke eine beliebige Taste um zu prüfen ob eine neue .wav im Verzeichnis ist.
pause>nul
 rem ebenfalls wie oben sortiert einlesen
for /f "tokens=*" %%a in ('dir  /tc /o-d  /b "*.wav"') do (
    rem im ersten Element ist des Arrays ist die Datei gespeichert, welche zuletzt erzeugt wurde (so gott will)
  if "%WavArray.1%" neq "%%a" (
    echo  "%%a" ist die neuste hinzugekommene .wav-Datei!
     rem fertig es gibt  keien Grund  für weitere Prüfungen
    goto :break
  ) else (
    echo keine neue Datei
    goto :check
  )
)
:break
pause

...allerding wäre in diesem Fall das Array Unsinn (wir brachen ja nur die jeweils neuste Datei):

@echo off
chcp 65001 >nul
for /f "tokens=*" %%a in ('dir /tc /o-d /b "*.wav"') do (
  set "NewestWav=%%a"
  goto :break
)
:break


:check
echo Drücke eine beliebige Taste um zu prüfen ob eine neue .wav im Verzeichnis ist.
pause>nul


for /f "tokens=*" %%a in ('dir  /tc /o-d  /b "*.wav"') do (
  if "%NewestWav%" neq "%%a" (
    echo  "%%a" ist die neuste hinzugekommene .wav-Datei!
    goto :break
  ) else (
    echo keine neue .wav-Datei
    goto :check
  )
)
:break
pause

ich wäre zu gespannt wie Du die Sache gelöst hat...

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren

Louis9911 
Beitragsersteller
 14.11.2022, 14:04

Danke. - Ich bin an der Entwicklung eines Menüsystems für Telefonanrufe. Dem Anrufer sollen u.a. zufällig ausgewählte Audiodateien (wav) vorgespielt werden (den Code dazu hast Du mir netterweise schon vorgeschlagen). Zufällig sollte es darum sein, um die Wahrscheinlichkeit der mehrfachen Wiedergabe desselben Audios zu minimieren. Ganz ausschliessen, zumindest für den aktuellen Anruf, lässt sich die mehrfache Wiedergabe ja nun, wenn man die bereits abgespielten Audios von der Gesamt-Dateimenge abzieht. Ich dachte erst, die Realisierung dieser Methode als cmd-Batch sei für mich zu schwierig bzw. die Einbettung in das Menüsystem. Mein Irrtum in meinem OP von diesem Thread war auch, dass es die neuste wav-Datei sein müsste in der Dateimenge abzüglich der schon gespielten Audios. Aber so würde dem selben Anrufer bei seinem nächsten Anruf immer dieselbe Reihenfolge abgespielt. Denn, Filtrierung mittels Anrufernummer ist leider nicht möglich, da mein Telcom-Anbieter nur die Mehrwertnummer übermittelt, wenn jemand darauf anruft. Wenn Letzteres nicht der Fall ist, wird die effektive Anrufernummer übermittelt. So müsste der Anrufer eine individulle Pin hinterlegen, damit bei seinem nächsten Anruf seine persönlichen bereits-abgespielt-Audios von der Gesamt-Dateimenge abgezogen werden könnte. - Nun, ich denke ich werde die Menge der bereits gespielten Audios auf diese Weise von der Gesamtmenge abziehen: Jede abgespielte Datei wird in ein temporäres Verzeichnis verschoben, so dass die Gesamtmenge, aus der per Zufall ein Audio gezogen wird, um diese bereits gespielte Datei kleiner wird. Bei Anrufende werden die Dateien im temporären Verzeichnis wieder zurückverschoben. Sehr einfach. Aber für meine Anforderung voll ausreichend.

Erzesel  14.11.2022, 18:44
@Louis9911

warum willst du die Liste der Dateinamen durchackern?

Es genügt doch völlig zu prüfen das die neue Zufallszahl nicht die gleiche ist wie die letzte:

@echo off
chcp 65001 >nul
for /f "tokens=1* delims=[]" %%a in ('dir /s /b "c:/windows\Media\*.wav" ^|find /v /n ""') do (
  set "myWavArray.%%a=%%b"
  set "myWavArray.Count=%%a"
)
if "myWavArray.Count"=="" (
  echo Keine wav!
  pause
  exit /b
)


  rem es kann nie 2 mal die  gleiche  Zahl gezogen werden (außer  es gibt  nur  eine Datei)
call :getNextRandom  MyNumber %myWavArray.Count%
echo %MyNumber%
call echo "%%myWavArray.%MyNumber%%%"
 rem nächste...
call :getNextRandom  MyNumber %myWavArray.Count%
echo %MyNumber%
call echo "%%myWavArray.%MyNumber%%%"


call :getNextRandom  MyNumber %myWavArray.Count%
echo %MyNumber%
call echo "%%myWavArray.%MyNumber%%%"


pause
exit /b


:::: Subroutines :::
 rem ermittle eine Zufallszahl, welche nicht mit der letzten übereinstimmt
:getNextRandom   %1=VariablenName  %2=höchste Zufallszahl
if "%~2"=="1" (
    set "%~1=1"
    exit /b 1
)
set /a "getNextRandom.NewRandomNumber=%random% %% %~2 +1"
if "%getNextRandom.LastRandomNumber%"=="%getNextRandom.NewRandomNumber%" (
    goto :getNextRandom
)
set "getNextRandom.LastRandomNumber=%getNextRandom.NewRandomNumber%"
set "%~1=%getNextRandom.NewRandomNumber%"
exit /b 0
Erzesel  14.11.2022, 19:44
@Louis9911

Oder du prüfst ob alle bisher gezogenen Zahlen schon mal da waren und fängst erst vom neuen an, wenn du alle durch hast:

@echo off
chcp 65001 >nul

set "maxNumber=5"

call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
echo:

call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
echo:

call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%
call :GetUniqueRandom MeineVariable %maxNumber%
echo %MeineVariable%

pause
exit /b

:::: Subroutines :::

:GetUniqueRandom  %1=VariablenName %2=höchste Zufallszahl
if "%~2"=="1" (
  set "%~1=1"
  exit /b 1
)
set /a "GetUniqueRandom.NewNumber=%random% %% %~2 +1"
 rem prüfe ob die Nummer bereits gezogen wurde
echo #%GetUniqueRandom.NewNumber%#|findstr /l "dummy %GetUniqueRandom.bisherigeNummern%" >nul && (
   rem wenn ja nochmal
  goto :GetUniqueRandom
)
 rem füge die neue Nummer der Aufzählung hinzu 
set "GetUniqueRandom.bisherigeNummern=%GetUniqueRandom.bisherigeNummern% #%GetUniqueRandom.NewNumber%#"
set /a "GetUniqueRandom.allNumbers+=1" &rem zähle mit, wievele Zahlen wir schon haben
set "%~1=%GetUniqueRandom.NewNumber%"

set "GetUniqueRandom." &rem mal anzeigen , kann weg


if %GetUniqueRandom.allNumbers% geq %~2 (
  echo setze Liste der bisher gezogenen Zahlen zurück! &rem Zeile kann weg
  set "GetUniqueRandom.bisherigeNummern="
  set "GetUniqueRandom.allNumbers=0"
)

mit den Dateien und ohne die Debugzeilen , sieht es dann so aus:

@echo off
chcp 65001 >nul
for /f "tokens=1* delims=[]" %%a in ('dir /s /b "c:/windows\Media\*.wav" ^|find /v /n ""') do (
 set "myWavArray.%%a=%%b"
 set "myWavArray.Count=%%a"
)
if "myWavArray.Count"=="" (
 echo Keine wav!
 pause
 exit /b
)

call :GetUniqueRandom MyIndex %myWavArray.Count%
echo %MyIndex%
call echo %%myWavArray.%MyIndex%%%

call :GetUniqueRandom MyIndex %myWavArray.Count%
echo Zufallszahl: %MyIndex%
call echo %%myWavArray.%MyIndex%%%

call :GetUniqueRandom MyIndex %myWavArray.Count%
echo Zufallszahl: %MyIndex%
call echo %%myWavArray.%MyIndex%%%

call :GetUniqueRandom MyIndex %myWavArray.Count%
echo Zufallszahl: %MyIndex%
call echo %%myWavArray.%MyIndex%%%

call :GetUniqueRandom MyIndex %myWavArray.Count%
echo Zufallszahl: %MyIndex%
call echo %%myWavArray.%MyIndex%%%
echo:

pause
exit /b

:::: Subroutines :::

:GetUniqueRandom  %1=VariablenName %2=höchste Zufallszahl
if "%~2"=="1" (
  set "%~1=1"
  exit /b 1
)
set /a "GetUniqueRandom.NewNumber=%random% %% %~2 +1"
echo #%GetUniqueRandom.NewNumber%#|findstr /l "dummy %GetUniqueRandom.bisherigeNummern%" >nul && (
  goto :GetUniqueRandom
)
set "GetUniqueRandom.bisherigeNummern=%GetUniqueRandom.bisherigeNummern% #%GetUniqueRandom.NewNumber%#"
set /a "GetUniqueRandom.allNumbers+=1"
set "%~1=%GetUniqueRandom.NewNumber%"

if %GetUniqueRandom.allNumbers% geq %~2 (
  set "GetUniqueRandom.bisherigeNummern="
  set "GetUniqueRandom.allNumbers=0"
)

die Liste der bisherigen ZufallsZahlen wird erst Zurück gesetzt wenn alle möglichen gezogen wurden...

Einen Wehrmutstropfen hat die Sache. Bei sehr vielen möglichen Zahlen, kann es eine Weile dauern, bis eine Zufallszahl gefunden wird, welche noch nicht da war:

@echo off
chcp 65001 >nul

set "maxNumber=300"

for /l %%a in (1,1,%maxNumber%) do (
    call :GetUniqueRandom  MeineVariable %maxNumber%
    call echo %%MeineVariable%%
)
pause
exit /b

:::: Subroutines :::

:GetUniqueRandom   %1=VariablenName  %2=höchste Zufallszahl
if "%~2"=="1" (
    set "%~1=1"
    exit /b 1
)
set /a "GetUniqueRandom.NewNumber=%random% %% %~2 +1"
echo #%GetUniqueRandom.NewNumber%#|findstr /l "dummy %GetUniqueRandom.bisherigeNummern%" >nul && (
    goto :GetUniqueRandom
)
set "GetUniqueRandom.bisherigeNummern=%GetUniqueRandom.bisherigeNummern% #%GetUniqueRandom.NewNumber%#"
set /a "GetUniqueRandom.allNumbers+=1"
set "%~1=%GetUniqueRandom.NewNumber%"

if %GetUniqueRandom.allNumbers% geq %~2 (
    set "GetUniqueRandom.bisherigeNummern="
    set "GetUniqueRandom.allNumbers=0"
)

siehe Fortsetzung...

Erzesel  14.11.2022, 19:46
@Louis9911

Fortsetzung:

so ist es besser:

@echo off
chcp 65001 >nul

set "maxNumber=300"

for /l %%a in (1,1,%maxNumber%) do (
  call :GetUniqueRandom2 MeineVariable %maxNumber%
  call echo %%MeineVariable%%
)
pause
exit /b

:::: Subroutines :::

:GetUniqueRandom2  %1=VariablenName %2=höchste Zufallszahl
if "%~2"=="1" (
  set "%~1=1"
  exit /b 1
)
set /a "GetUniqueRandom2.NewNumber=%random% %% %~2 +1"
echo #%GetUniqueRandom2.NewNumber%#|findstr /l "dummy %GetUniqueRandom2.bisherigeNummern%" >nul && (
  goto :GetUniqueRandom2
)
set "GetUniqueRandom2.bisherigeNummern=%GetUniqueRandom2.bisherigeNummern% #%GetUniqueRandom2.NewNumber%#"
set /a "GetUniqueRandom2.allNumbers+=1"
set "%~1=%GetUniqueRandom2.NewNumber%"

set "GetUniqueRandom2.Limit=%~2"

 rem sollte ok sein, wenn sich Zahlen nach 20x wiederholen können 
if %GetUniqueRandom2.Limit% gtr 20 (
  set "GetUniqueRandom2.Limit=20"
)

if %GetUniqueRandom2.allNumbers% geq %GetUniqueRandom2.Limit% (
  set "GetUniqueRandom2.bisherigeNummern="
  set "GetUniqueRandom2.allNumbers=0"
)