(1) Erkennen der Frage nach einem Witz.

Da du anscheinend schon einen funktionierenden Chatbot hast, sollte das ja recht einfach gehen. Du musst also nur z.B. die Keywords Witz, lustig, etc. hinzufügen.

(2) Metadaten über deine Witzdatei erfassen.

Du brauchst hier lediglich die Anzahl an Zeilen, um dir später dann eine davon zufällig aussuchen zu können. Mit einer for-Schleife kannst du die ganz simpel zählen.

(3) Eine Zeile zufällig auswählen.

Die durch %random% generierte Zufallszahl auf den hier benötigten Zahlenbereich von [1; Zeilenlänge] bringen. Sehr simple, wenn auch nicht optimale Methode hierfür wäre:

set /a selectedLine=%random% %% lines + 1

(4) Die Zeile ausgeben.

Du traversierst hierfür alle Zeilen deiner Witze-Datei und gibst die Zeile mit der zuvor berechneten Zeilennummer aus. Dies kannst du mithilfe von findstr /n, mit einer Hilfsvariable oder mittels dekrementieren der selectedLine-Variable erledigen.

Die Schritte 2 bis 4 habe ich in dieser Antwort schon für Verzeichnisse umgesetzt:

https://www.gutefrage.net/frage/cmd-zufaelliges-wort#answer-347286974

Du musst die for-Schleifen also nur noch anpassen, dass sie sich auf Textdateien beziehen.

...zur Antwort

Ein Skript um bestimmte Dateien zu suchen, habe ich vor kurzem erst für diese Frage hier geschrieben. Das sieht dann ungefähr so aus:

@echo off

:: CONFIG ::
set searchDirectory="C:\User\"
set searchString="test.txt"
:: CONFIG ::

set result="%TEMP%\search_result.txt"
cd /D %searchDirectory%
dir /s /b | findstr %searchString% > %result%

:read
set amount=0
for /f "usebackq tokens=*" %%f in (%result%) do (
    set /a amount += 1
)

if %amount% equ 0 (
    echo Datei wurde nicht gefunden.
    del %result%
    pause & exit /b 1
)
if %amount% gtr 1 (
    echo Mehrere Dateien gefunden.
    echo Druecken Sie eine beliebige Taste um alle gefundenen Dateien angezeigt zu bekommen.
    echo Loeschen Sie dann alle ungewuenschten Zeilen, sodass am Ende nur die zu kopierende Datei in der ersten Zeile steht.
    echo Dann speichern Sie ihre Auswahl mit [Strg] + [s] und schliessen das Fenster.
    pause
    notepad %result%
    goto read
)

set /p file=<%result%
del %result%
echo Gefundene Datei: %file%
pause

Die Funktionalität zum Ersetzen der Datei kannst du entweder schnell selbst am Ende einbauen, oder du erklärst genauer, was getan werden soll.

...zur Antwort

Habe dir mal eben eine kleine Batch hierfür geschrieben. Das eigentliche Suchen der Datei wird dabei so erledigt:

dir /s /b | findstr %searchString%

Das komplette Programm kann dann auch mit mehreren gefundenen Dateien umgehen und erledigt auch das kopieren. Die Parameter im CONFIG-Bereich kannst du je nach deinen Anforderungen anpassen.

@echo off

:: CONFIG ::
set searchDirectory="C:\User\"
set searchString="test.txt"
set outputFolder="D:\output"
:: CONFIG ::

set result="%TEMP%\search_result.txt"
cd /D %searchDirectory%
dir /s /b | findstr %searchString% > %result%

:read
set amount=0
for /f "usebackq tokens=*" %%f in (%result%) do (
    set /a amount += 1
)

if %amount% equ 0 (
    echo Datei wurde nicht gefunden.
    del %result%
    pause & exit /b 1
)
if %amount% gtr 1 (
    echo Mehrere Dateien gefunden.
    echo Druecken Sie eine beliebige Taste um alle gefundenen Dateien angezeigt zu bekommen.
    echo Loeschen Sie dann alle ungewuenschten Zeilen, sodass am Ende nur die zu kopierende Datei in der ersten Zeile steht.
    echo Dann speichern Sie ihre Auswahl mit [Strg] + [s] und schliessen das Fenster.
    pause
    notepad %result%
    goto read
)

set /p file=<%result%
del %result%
cd /D %outputFolder%
copy "%file%"
pause
...zur Antwort

Für arithmetische Operationen steht dir `set/a` zur Verfügung:

set /a minutes = 5
set /a seconds = minutes * 60

Die Berechnung muss dabei vor dem shutdown-Befehl ausgeführt werden. Dein Beispiel muss also so aussehen:

set /a Wert *= 60
shutdown -s -t %Wert% -f

`set /a Wert *= 60` ist dabei eine Kurzschreibweise für

set /a Wert = Wert * 60

mit der du den Variablennamen nicht zweimal hinschreiben musst.

...zur Antwort

In Batch hast du neben "==" noch folgende Vergleichsoperatoren zur Verfügung:

    EQU - gleich
    NEQ - nicht gleich
    LSS - kleiner als
    LEQ - kleiner als oder gleich
    GTR - größer als
    GEQ - größer als oder gleich

Also um zwei Zahlen zu vergleichen:

set /a a = 5
set /a b = 7

if %a% leq %b% (
    echo a ist kleiner als oder gleich b
)

Beim Datum allerdings hast du das Problem, dass du meist keine Zahlen, sondern Strings in einem bestimmten Datumsformat vorliegen hast.

Das Datumsformat von %date% kann zudem auf unterschiedlichen Computern variieren. Darum ist es besser das Datum mit z.B. `wmic os get LocalDateTime /VALUE` abzufragen. Das speichern dieses Wertes kannst du mit for erledigen:

for /f "tokens=1,2 delims==" %%d in ('wmic os get LocalDateTime /VALUE') do (if "%%d" equ "LocalDateTime" set dt=%%e)

Da du dich beim Datum nur für die ersten 8 Stellen interessierst, kannst du den Rest abschneiden; Ich füge zudem gerne zwischen Jahr, Monat und Tag noch Striche "-" ein, damit das Datum besser lesbar ist:

set currentDate=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%

Mit `if` kannst du nun einen Stringvergleich mit einem anderen Datum (im selben Format) durchführen:

if "%currentDate%" gtr "%maxDate%" goto licenseExpired

Hier mal ein ganzes Beispielprogramm:

for /f "tokens=1,2 delims==" %%d in ('wmic os get LocalDateTime /VALUE') do (if "%%d" equ "LocalDateTime" set dt=%%e)
::  dateFormat:=   YYYY  -    MM   -   DD
set currentDate=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%
set maxDate=2020-05-10

if "%currentDate%" gtr "%maxDate%" goto licenseExpired

echo passed.
pause&exit

:licenseExpired
echo error. license expired.
pause&exit
...zur Antwort

Da %PFAD% wahrscheinlich einfach immer das Verzeichnis sein soll, in dem die Batch-Datei liegt, kannst du stattdessen einfach %~dp0 verwenden.

Hierbei erstellst du mithilfe der Variable %0, in der immer der Pfad zur eigenen Datei enthalten ist, den Laufwerksbuchstaben und Pfad davon. Diese bleibt auch identisch, nachdem du das aktuelle Arbeitsverzeichnis per cd geändert hast.

Bei `cd` solltest du vielleicht auch die Option /D verwenden, um zusätzlich zum Pfad auch das Laufwerk wechseln zu können.

Zudem ist es sinnvoll auch die Existenz des "Program Files (x86)"-Ordners zu überprüfen.

...zur Antwort
set /a %Versuch%-1

gibt dir in der cmd lediglich den Wert Versuch-1 aus, genauso wie:

set /a summonNr-1

Um die Variable auch zu setzen, brauchst du auch noch ein Gleichheitszeichen:

set /a summonNr-=1

(Ist übrigens die Kurzschreibweise für `set /a summonNr = summonNr-1`, bei set/a kannst du die Prozentzeichen weglassen, da alle Buchstabenfolgen als Variablen interpretiert werden. Leerzeichen kannst du bei set/a auch fast beliebig setzen, also z.B.)

Und die Überprüfung auf 0 würde ich auch noch korrigieren. Hierfür gibt es mehrere verschiedene richtige Arten, z.B.:

if %summonNr% equ 0 goto SummonError

oder

if "%summonNr%"=="0" goto SummonError
...zur Antwort
echo.Zeile1>"file.txt"
echo.>>"file.txt"
echo.Zeile2>>"file.txt"

Du überschreibst mit echo...>... den Inhalt der Datei. Mit >> hängst du einen neue Zeile an.

...zur Antwort

Wenn es nur darum geht einen Ordner zu erstellen, falls er nicht existiert, kannst du dir den Keks eigentlich sparen:

set d=%userprofile%\desktop\test
if not exist "%d%\" md "%d%"

Aber mkDir (kurz: md) überprüft auch selbst, ob der Ordner bereits existiert und gibt eine Meldung aus, wenn dies der Fall ist. So kannst du dir die Abfrage sparen und einfach die eventuell auftretende Meldung unterdrücken:

md "%userprofile%\desktop\test" 2>nul
...zur Antwort

Bei einer Batch-Datei mit ausschließlich folgendem Inhalt, wird überhaupt nichts angezeigt, der Befehl aber erfolgreich ausgeführt:

@findstr /v "Test" Quelle.txt >Ziel.txt

(Zum Überprüfen einfach ein pause anhängen)

Dein Problem muss folglich wo anders liegen. Was funktioniert denn nicht und was passiert stattdessen?

...zur Antwort

Ich glaube der Fehler steckt in deiner zweiten for-Schleife. Zunächst fällt auf, dass du statt einfach nur den String %%f anzugeben diesen mit echo schreibst (das ist zwar unnötig, sollte aber noch kein Grund für einen Fehler sein). Da du die for-Schleife ausschließlich zum setzen einer Variablen verwendest, die du auch so setzen könntest, ist diese komplett unnötig. Vielmehr ist diese Variable sogar die Fehlerquelle: Sie ist zu Beginn noch nicht definiert, da cmd erst die Variablen durch ihre Werte ersetzt und dann anfängt den Code auszuführen. In deinem Fall ist das ganze aber leicht zu beheben (auch ohne DelayedExpansion, mit der Variablen verzögert ausgelesen werden können): Da du die Variable nur einmal brauchst, kannst du sie komplett weglassen und an der Stelle direkt ihren variablen Wert eintragen:

@echo off
set /p "ort=Verzeichnis: "
set /p "vorsilbe=Vorsilbe: "
echo.
echo Veraenderte Dateien:
for /R "%ort%" %%F in (.) do (
    echo."%%F"
    rename "%%~fF" "%vorsilbe%%~nxF"
)
pause

Habe mir jetzt keine Ordnerstruktur angelegt und getestet, müsstest mal eben selber schauen, ob es jetzt funktioniert.

PS: Nachdem du nur veränderte Dateien ausgeben willst, ist das hier vielleicht besser geeignet:

@echo off
set /p "ort=Verzeichnis: "
set /p "vorsilbe=Vorsilbe: "
echo.
echo Veraenderte Dateien:
for /R "%ort%" %%F in (.) do (
    ren "%%~fF" "%vorsilbe%%~nxF" && echo."%%F"
)
pause
...zur Antwort
setlocal enableDelayedExpansion
for /F "tokens=*" %%L in (datei.txt) do (
    set /a line += 1
    if !line! equ 5 ( 
        echo verändere die Zeile oder lasse sie weg...
    ) else ( 
        echo.%%L
    )
)>>"%TMP%\tmpOutput[%~n0].txt"
del "datei.txt"
copy "%TMP%\tmpOutput[%~n0].txt" "datei.txt"

Beispiel für die Datei datei.txt, vorrausgesetzt du willst eine bestimmte Zeile (hier 5) ändern. Ist das nicht der Fall brauchst du line nicht und kannst zum Beispiel bestimmte Zeichenfolgen ersetzten:

setlocal enableDelayedExpansion
for /F "tokens=*" %%L in (datei.txt) do (
    set "line=%%L"
    set "line=!line:suchString=ersetzString!"
    echo.!line!
)>>"%TMP%\tmpOutput[%~n0].txt"
del "datei.txt"
copy "%TMP%\tmpOutput[%~n0].txt" "datei.txt"
...zur Antwort

Wäre ja blöd, wenn ein Befehl zum Auswählen von Buchstaben, immer beim Auswählen von Buchstaben Probleme hat.

Erkläre also dein Problem detailliert und am besten mit einem minimalen Codebeispiel, mithilfe dessen dein Problem reproduzierbar ist.

...zur Antwort
[...] ohne immer auf eine neue Sprungmarke zu verweißen?

Springst du sonst bei jeder if-Abfrage zu einer Sprungmarke?

Du kannst Code nämlich auch direkt hinter die if-Abfrage schreiben und diesen sogar als Block über mehrere Zeilen fortführen:

if not exist beispiel.txt echo Datei nicht gefunden.

Hier ein (sinnloser) Beispiel-Block:

if "%variable%"=="Beispiel" (
    set variable=0
    pause
    cls
)

Mit den Klammern lässt sich auch ein else-Block verwenden, der ausgeführt wird, wenn die Bedingung nicht zutrifft. Zudem lassen sich weitere if-Abfrage verwenden:

@echo off

if "%date:~0,6%"=="24.12." (
    echo Heute ist Weihnachten
) else (
    if %date:~3,2% GEQ 10 (
        echo Nicht mehr lange bis Weihnachten
    )
)

pause

Um zu deiner Frage zurück zu kommen:

Ein und gibt es in Batch nicht, ist aber so auch nicht viel umständlicher:

if <Bedingung1> if <Bedingung2> [(] <Befehl[e]> [)]

also zum Beispiel:

@echo off
choice /m "Beliebige Ziffer eingeben: " /c 0123456789 /n
set /a ziffer = %errorlevel% - 1

:: überprüfe ob ziffer im Bereich [3;6]
if %ziffer% GEQ 3 if %ziffer% LEQ 6 (
    echo ziffer im Bereich [3;6]
) else (
    echo ziffer groesser als 6
) 

pause

Das Problem ist hier, das sich das else nicht auf beide Bedingungen bezieht, sondern nur auf die letzte, möchte man ein else im Sinne von

if not <Bedingung1> if not <Bedingung2>

muss man das entweder extra so hinschreiben, oder man verwendet Variablen/Sprungmarken (wie bei oder).

Problematischer wird es, wenn du ein oder verwenden willst. Also zum Beispiel "Zahl kleiner als 2 oder größer als 7"

Da könntest du natürlich auch wieder mit Sprungmarken arbeiten:
(Notiz: die Abfrage in dem Beispiel könnte natürlich stark vereinfacht werden, indem man nach GEQ 2 und LEQ 7 abfragt, aber soll ja nur ein Beispiel sein)

:: Anfangscode wie oben ::

if %ziffer% LSS 2 goto true
if %ziffer% GTR 7 goto true

echo Die ziffer ist groesser als 1 und kleiner als 8
goto continue

:true
echo Die Ziffer ist 0,1,8 oder 9

:continue
pause
exit

schöner denke ich wäre in dem Fall aber eine Variable:

:: Anfangscode wie oben ::

set "bool=false"
if %ziffer% LSS 2 set "bool=true"
if %ziffer% GTR 7 set "bool=true"

:: und dann reicht eine if-Abfrage
if %bool% equ true (
    echo Die Ziffer ist 0,1,8 oder 9
) else (
    echo Die ziffer ist groesser als 1 und kleiner als 8
)

pause
exit

FAZIT: Das beste ist wohl, zumindest für kompliziertere Fälle, mithilfe von mehreren if-Abfragen eine Variable zu setzten, mit der du dann eine finale if-Abfrage (inklusive else) durchführen kannst.

~Tim

...zur Antwort

Willst du zum Beispiel 25% von einer Variablen abziehen:

set /a zahl    = 200
set /a percent = 25
set /a zahl   -= zahl * percent / 100

beachte dabei, dass du mit set /a nur mit Integern rechnen kannst, bei

set /a zahl    = 7
set /a percent = 25
set /a zahl   = zahl * percent / 100

käme zum Beispiel 6 raus, da bei 1.75 alles nach dem Komma "weggelassen" wird und cmd demnach 7 - 1 = 6 rechnet.

Um das zumindest teilweise zu umgehen könntest du erst am Ende durch 100 teilen:

set /a zahl    = 7
set /a percent = 25
set /a zahl    = (zahl*100) - (zahl*percent)
set /a zahl   /= 100

Dadurch kommt jetzt eigentlich immer das richtige Ergebnis raus, aber halt mit abgeschnittenen Kommazahlen. (In diesem Fall 5 statt 5.25)

Um jetzt die wirklich richtige Zahl zu bekommen muss man noch etwas weiter gehen:

Ich habe dazu mal einen eigenen "Batch-Befehl" geschrieben: github.com/timlg07/Batch_Tools/3-2-division.cmd

Wie du die Datei benutzt erfährst du hier (github.com/timlg07/Batch_Tools/3-2-division.txt) und alle Infos zur Syntax erfährst du so:

divide/?

Du könntest das obige Beispiel dann mit dem divide Befehl ergänzen:

set /a zahl    = 7
set /a percent = 25
set /a zahl    = (zahl*100) - (zahl*percent)
divide %zahl%/100

Um das dann wieder in eine Variable einzulesen:

set /a zahl    = 7
set /a percent = 25
set /a zahl    = (zahl*100) - (zahl*percent)
for /f %%e in ('divide %zahl%/100') do set zahl=%%e

So hast du in %zahl% nun endlich die 5.25!

Falls du noch nicht mit GitHub gearbeitet hast und dir das zu kompliziert ist, einfach folgenden Code in eine Batch kopieren (wenn du die gleich divide.cmd nennst, musst du sie vor dem verwenden auch nicht mehr ausführen)

@echo off & setlocal enableDelayedExpansion
if "%1"=="" goto noArgs

echo.%* | find /I "/?" >nul && goto info
echo.%* | find /I "/HELP" >nul && goto info

for /F "tokens=1* delims=/" %%A in ("%~1") do (
	set "dividend=%%A"
	set "divisor=%%B"
)

if not defined dividend set dividend=NAN
if not defined divisor  set  divisor=NAN

if not "%~2"=="" ( set "decimalPlaces=%~2"    ) else ( set "decimalPlaces=6"    )
if not "%~3"=="" ( set "decimalSeperator=%~3" ) else ( set "decimalSeperator=." )


call :expand dividend
call :expand divisor

call :checkNumber dividend
call :checkNumber divisor
call :checkNumber decimalPlaces


call :division
echo %result%
exit /B

:expand
	set "%~1=!%~1:RANDOM=%random%!"
	set "%~1=!%~1:MAX=2147483647!"
	set "%~1=!%~1:PI=3!"&rem 3.141592654
	set "%~1=!%~1:E=3!" &rem 2.718281828
exit /B

:checkNumber
	call :trim "%~1"

	set "varName=%~1"
	set "varCont=!%~1!"
	set /a varContNumber=varCont

	if %varContNumber% EQU 0 (
		if not "%varCont:0=%"=="" (
			call :onError NAN %varName%
			set /a varCont=1
		)
	)
	call :deleteLeadingZero "%varCont%"
	set "%varName%=%errorlevel%"
exit /B

:trim
	set "%~1=!%~1: =!"
exit /B

:deleteLeadingZero
exit /B %~1

:onError
	if /I "%~1"=="NAN" (
	    echo ERROR_NAN at checkNumber
		echo "!%~2!" is not a number.
	)
exit /B


:division
	
	set /a int= dividend / divisor
	set "result=%int%%decimalSeperator%"
	set /a remainder=dividend-(int*divisor)
	set /a decP=0
	:div_LOOP
		set /a intR=(remainder*10)/divisor
		set /a remainder=(remainder*10)-(intR*divisor)
		set result=%result%%intR%
		set /a decP+=1
		if %remainder% EQU 0 exit /b 0
		if %decP% GEQ %decimalPlaces% exit /b 1
	goto div_LOOP
exit /B

	
:noArgs
	echo Keine Argumente.
	echo weitere Infos: divide /?
goto checkName

:info
	echo.
	echo Syntax:
	echo.
	echo DIVIDE Integer/Integer [decimalPlaces [decimalSeperator]]
	echo.
	echo.
	echo Returns an float value with the given
	echo amount of decimal places. (Default:6)
	echo.
	echo The decimal seperator can be "." or "," 
	echo or any other character. (Default:".")
	echo.
	echo Following variables can be used:
	echo RANDOM ^| expands to a random integer
	echo MAX    ^| expands to the integer max value
	echo PI     ^| expands to the value of pi
	echo E      ^| expands to the value of e
	echo.
	echo (PI and E are both 3 because floats in input are not supported yet)
	echo.
exit /b

:checkName
	if /i not "%~n0"=="DIVIDE" copy "%~nx0" "divide%~x0" >nul
exit /B

~Tim

...zur Antwort

Direkt gibt es, wie du richtig erkannt hast, keine while-Schleife.

Meistens nutzt man hierfür dann die Sprungmarken:

:WHILE
if not <die Bedingung, die normal in while(...) kommen würde> goto WHILE_end
    ::dein Code
goto WHILE
:WHILE_end

bzw.

:DO_WHILE
    ::dein Code
if <gleiche Bedingung wie Bsp1> goto DO_WHILE

Die Syntax ist natürlich länger und umständlicher als gewöhnlich und man muss aufpassen keine Sprungmarke doppelt zu verwenden.

Alternativ kannst du auch die for-Schleifen missbrauchen:

while(true)

for /L %%i in (0,0,1) do echo spam

while(x<5)

@echo off & setlocal EnableDelayedExpansion
for /L %%i in (0,0,1) do (
    set x=%random:~0,1% 
    echo %x%
    if %x% geq 5 goto break
)
:break
pause

aber da würde ich dann die Sprungmarken bevorzugen, da muss man nicht mit delayedExpansions arbeiten.

~Tim

...zur Antwort

Zunächst mal kurz die Antwort auf deine Frage: >>DelayedExpansions<< ;P

mithilfe von

setlocal enableDelayedExpansion

kannst du Variablen auch mit !var! verzögert auslesen:

@echo off & setlocal enableDelayedExpansion
set "var[0]=test"
set "index=0"
echo !var[%index%]!
:: alternativ ::
call echo %%var[%index%]%%
pause>nul

Jetzt noch kurz zur for-Schleife, mit der du leicht über dein Array iterieren kannst:

:: folgende Zeile ersetzt deinen ganzen vorherigen Code ::
for /L %%i in (0,1,100) do set z%%i=!random!

Hier also ein komplettes Beispiel zum setzten und auslesen deines Arrays: (sinnvoll ist es auch noch, wenn du dir die Länge des Arrays in einer Variablen speicherst)

setlocal enableDelayedExpansion
for /L %%i in (0,1,100) do set z%%i=!random!
for /L %%i in (0,1,100) do echo !z%%i!
pause

(Die delayedExpansion bei random brauchst du, da random sonst direkt durch einen Wert ersetzt wird und nicht bei jedem Schleifendurchlauf neu)

~Tim

...zur Antwort

Das taskkill keinen Suchfilter erkannt hat, liegt daran, dass du gar keinen angegeben hast... Woher soll taskkill denn wissen, ob du nach status, nutzername, CPU time oder eben dem Fenstertitel filtern willst?

In deinem Fall also:

taskkill /F /FI "WINDOWTITLE eq WINDOW C" /IM cmd.exe /T

~Tim

...zur Antwort

Ich benutze meistens folgendes und hatte noch nie Probleme damit:

FOR /F "delims=" %%L in (datei.txt) do echo/%%L

Dass dein for-Loop nicht wie gewünscht funktioniert liegt daran:

Standardmäßig liefert "/F" den ersten, durch ein Leerzeichen getrennten Token von jeder Zeile in jeder Datei. Leerzeilen werden übersprungen. Das standardmäßige Verhalten bei der Analyse kann wahlweise durch den Parameter "Optionen" überschrieben werden.
~ Hilfe von for [ for/?]

Alternativ sollte auch das hier funktionieren: (tokens=* wählt praktisch die ganze Zeile aus.)

FOR /F "tokens=*" %%L in (datei.txt) do echo/%%L

Lies dir dazu am besten die Hilfe von for durch. Hier das wichtigste zu den Optionen (wie delims oder tokens):

eol=c      - Gibt das Zeichen für Zeilenendekommentare an
             (nur eins).
skip=n     - Gibt die Anzahl der Zeilen an, die am Anfang einer
             Datei übersprungen werden.
delims=xxx   - Gibt einen Satz von Trennzeichen an. Diese ersetzen
             die Standardtrennzeichen TAB und Leerzeichen.
tokens=x,y,m-n - Gibt an, welche Token von jeder Zeile an die
             FOR-Schleife weitergegeben werden.
             Das führt dazu, dass zusätzliche Variablen erstellt
             werden. Mit der Form m-n wird dabei ein Bereich vom
             m-ten bis zum n-ten Token angegeben. Wenn das letzte
             Zeichen ein Sternchen ist, wird eine zusätzliche
             Variable deklariert, die den verbleibenden Text
             dieser Zeile enthält.
usebackq    - Gibt an, dass die neue Semantik in Kraft ist,
             wobei eine Zeichenfolge in umgekehrten Anführungs-
             zeichen als Befehl ausgeführt wird und eine
             Zeichenfolge in Anführungszeichen ein literaler
             Befehl ist, der die Verwendung von doppelten
             Anführungszeichen um Dateinamen in Dateien-
             sätzen erlaubt.

Zum besseren Verständnis sind in der Hilfe auch Beispiele enthalten.

~Tim

...zur Antwort

Hier mit Batch: (ich bin mal davon ausgegangen, dass es, wie du gesagt hast, Ordner sind, auch wenn die Namen eher nach Dateien ausschauen)

for /D %%D in (*) do copy /b "%%~D\*" "%%~D\complete.ts" & del %%~D\data*.ts

Wenn du nur jeweils eine Datei in einem Ordner hast, finde ich wird der Ordner unnötig, hier eine Variante, die dir die Dateien in den übergeordneten Ordner legt und den ursprünglichen Ordner löscht:

for /D %%D in (*) do copy /b "%%~D\*" "%%~nD.ts" & rd /s /q "%%~D"

~Tim

...zur Antwort