[gelöst] Bilder-Sammlung durchnummerieren

Palladin007

assimiliert
Das ist mein Programm:

Code:
set work=1
:work
if exist %work%-*.jpg (
    set /a work=%work%+1
    goto work
) else (
    goto for
)

:for
set zähler=1
for /f %%i in ('dir /b *.jpg') do (
ren "%%i" "%work%-%zähler%.jpg"
set /a zähler=%zähler%+1
)

Es ist nur ein Ausschnitt von dem ganzen Programm, aber dort ist der Fehler. Und dieser Teil sieht dem dritten und letztem Teil meines Programmes sehr ähnlich, ich hoffe also, dass ich hier aus meinen Fehlern lernen kann^^

Es sind zwei Teile. Der erste Teil hat die Aufgabe, sicher zu stellen, dass das Namens-Muster, was erstellt werden soll, noch nicht existiert.

Der zweite Teil benennt die Datein dann in das neue Namens-Muster um.

Als erstes wird die Variable zähler fest gelegt. Die dient nur zum zählen, wie der Name ja schon sagt.
Als zweites kommt die for-Schleife. Sie erfasst jedes jpg-Bild im Ordner und übergibt den Namen an die darauf folgenden Zeilen.
Und dort wird dann jeder Name geändert. Vorne steht %work% mit der Zahl, die garantiert, dass die neuen Namen kein zweites mal vorkommen und dahinter der Zähler, damit die Namen untereinander verschieden sind.
Und dann zählt der Zähler weiter
Die For-Schleife beginnt von vorne


Aber da liegt das Problem.
Die erste Datei wird so umbenannt, wie ich das auch will, aber der Zähler zählt danach nicht weiter.
Der bleibt auf 1 stehen, auch wenn bei jedem Durchlauf +1 gerechnet wird.
Ich blicks nicht, denn die Variable wird doch nur einmal eindeutig definiert und das ist FOR der Schleife, aber warum bleibt sie dann trotzdem auf 1 stehen, selbst wenn sie geändert wird?

Was hab ich falsch gemacht?
 
Ohne das jetzt getestet und im einzelnen analysiert zu haben, behaupte ich mal, dass du den Namen for nicht als Sprunglabel verwenden darfst, da es ein reserviertes Wort (for-Befehl) ist. Benenne das Sprungziel um und versuche es damit nochmal. Auch würde ich Umlaute in den Variablennamen besser vermeiden, obwohl ein entsprechender Test bei mir gerade funktioniert hat.

edit:
Gerade ausprobiert, da ich einen Verdacht hatte:
In der Befehlszeile
set /a zähler=%zähler%+1
müssen Leerzeichen um das Plus herum eingefügt werden, sonst kommt es zum Fehler "Unbekannter Befehl":
set /a zähler=%zähler% + 1
 
Die Sprungmarke hab ich geändert, aber die Variable "zähler" bleibt trotzdem auf 1 stehen.

Und das mit den Umlauten mach ich schon immer so, auf die Weise bin ich einfach schneller, als wenn ich noch auf Umlaute achten müsste.

Dann muss ich nur bei den Text-Passagen aufpassen, die angezeigt werden sollen, aber auch dafür hab ich Lösung.


Ne, das beides kann es nicht sein.


Ich vermute, dass das mit der for-Schleife zusammen hängt, dass die for-Schleife, die ja mit anderen Namen immer wieder von vorne beginnt, auch die zähler-Variable wieder auf den Stand bringt, wie sie beim ersten Start war.

Aber das ist nur eine Vermutung

Kannst du damit was anfangen?
 
Das hab ich nie gemacht. Egal, was ich geschrieben habe, es waren nie Lehrzeichen dazwischen und es hat immer funktioniert.

Habs mal ausprobiert und es löst das Problem auch nicht :(


Ich löse den Problem-Fall mal aus dem Programm raus, lass es laufen und gebe dir die Ausgabe. Vieleicht kannst du ja damit was anfangen. Mir sagt das dann nur, dass die Variable vor jedesmal Plus-Rechnen irgendwie wieder auf 1 kommt.
 
So, das Programm sieht jetzt so aus:

Code:
set zähler=1
for /f %%i in ('dir /b *.jpg') do (
ren "%%i" "%zähler%.jpg"
set /a zähler=%zähler% + 1
)
pause

Es tut immer noch das selbe, nur hab ich die work-Variable raus genommen.
Jetzt ist das Programm nur sehr anfällig, denn sobald eine Datei 1.jpg heist, gehts nicht mehr.

Und trotzdem passiert das:

Code:
G:\Bilder>set zõhler=1

G:\Bilder>for /F %i in ('dir /b *.jpg') do (
ren "%i" "1.jpg"
 set /a zõhler=1 + 1
)

G:\Bilder>(
ren "ghjk.JPG" "1.jpg"
 set /a zõhler=1 + 1
)

G:\Bilder>(
ren "guilg.jpg" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>(
ren "jklö.JPG" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>(
ren "klöä.JPG" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>(
ren "sdfg.JPG" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>(
ren "sdfgs.jpg" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>(
ren "sdfgsd.jpg" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>(
ren "sdfgsdf.jpg" "1.jpg"
 set /a zõhler=1 + 1
)
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.

G:\Bilder>pause
Drücken Sie eine beliebige Taste . . .
verborgener Text:
õ steht für ä
Und da steht G:\, weil ich mein gesammtes Nutzerkonto auf meiner externen Fesplatte gespeichert habe.



Eine Datei wird wie gehabt korrekt umbenannt: 1.jpg
Dann müsste der Zähler eigendlich die zähler-Variable um 1 erweitern, sodass die nächste Datei dann 2.jpg heist.
Aber die Variable bleibt auf 1 stehen und deswegen bleibt auch der Name 1.jpg. Da die ja schon existiert, gehts nicht. -.-
 
Jetzt musste ich erst nochmal suchen und probieren, denn ich dachte auch, dass es so, wie von dir gezeigt, funktionieren sollte.

Versuche mal folgendes und füge den gezeigten Parameter mit ein:
aus
for /f %%i in ('dir /b *.jpg') do (
wird dann
for /f "tokens=*" %%i in ('dir /b *.jpg') do (
...

PS: Das mit den weiter oben genannten Leerzeichen war tatsächlich nur bei der Take Command Console so der Fall, die Syntax ist da etwas strenger, mit cmd.exe macht das keinen Unterschied. Ich muss für solche Demo-Fälle also doch das alte Windows-Teil verwenden.
 
Schade, ich sehe schon, so auf die Schnelle wie ich dachte geht das nun doch nicht. :unsure:
Da muss ich mich doch mal wieder in Ruhe in die alte cmd-Syntax neu einarbeiten, selber nutze ich schon seit Jahrzehnten nur noch Take Command Batches (war ganz früher mal 4DOS und 4NT), damit geht sowas viel einfacher und weniger kryptisch.

Aber hier gibt es ja noch mehr Boardies, von denen sich einige gut damit auskennen, da wird sich sicher noch jemand mit einer funktionierenden Lösung melden. :)
 
Naja, gelegentlich kommen von mir auch schwierige Fragen :D

Und ich kann versichern, sie werden nicht leichter, also wer es mag zu knobeln, wird später noch seine Freude an meinen Fragen haben^^

Und ich hoffe, ich bekomme hier produktive Antworten oder zumindest die Nachricht, dass keine Lösung parat ist.

Auf WinBoard - Die Windows Community hab ich gerne die Antwort bekommen, ich soll doch lieber eine neue Sprache lernen. Oder ich krieg gar keine Antwort...
 
Und ich hoffe, ich bekomme hier produktive Antworten oder zumindest die Nachricht, dass keine Lösung parat ist.
Geht nicht, gibt's nicht, sag ich immer.
Kann eigentlich nur eine Kleinigkeit in deinem Fall sein, die ich aber jetzt auch leider nicht erkenne.
Da kommt mit Sicherheit noch eine Lösung, so blöde Antworten wie in manch anderen Foren gibt es hier so gut wie nie.:)
 
Geht nicht, gibt's nicht, sag ich immer.
Da stimme ich dir vollkommen zu

Aalso, ich persönlich sehe da keinen Fehler, aber mach mal ganz am Anfang ein @ Echo on , damit alle Meldungen angezeigt werden.
Danach startest du die BAT mal direkt im CMD (per CD hinnavigieren, dann ausführen) - Hat den Vorteil, dass das CMD-Fenster nicht zugeht, wenns fertig ist.

Ansonsten versuch mal nach jedem Befehl mittels "if Errorlevel" (heist glaub ich so) zu testen, um zu sehen, wo der Fehler steckt...



ot:
Geht nicht, gibt's nicht, sag ich immer.
Da kommt mit Sicherheit noch eine Lösung, so blöde Antworten wie in manch anderen Foren gibt es hier so gut wie nie.:)[/QUOTE]
Natürlich nicht, denn dafür sind wir im SNF ja viel zu nett und kompetent *Eigenlob*
 
Ich werd deine Idee mal durchprobieren, CreamyCewie.


Aber bis dahin hab ich noch das für euch:

Code:
@echo off

set kon=1
set varname=0

for /f %%i in ('dir /b *.jpg') do call :kontroll %%i

:kontroll
if %1==%kon%.jpg (
    set /a kon=%kon%+1
) else (
    echo %1 >> zwischenspeicher.txt
)

pause

Dieses Programm funktioniert.
Es soll die Dateien raus suchen, die nicht der Reihenfolge 1 2 3 4 5 6 . . . entsprechen und als txt speichern. Tuts auch, die Frage ist dabei nur, warum zählt hier der Zähler richtig?
Da hab ich es doch eigendlich nicht sonderlich anders gemacht.

Und das hab ich auch noch:

Code:
@echo off

for /f %%i in ('dir /b *.jpg') do call :name %%i

:name
set /a zähler=%zähler%+1
ren "%1" "%zähler%.jpg"

pause

Das soll dann die Dateien alle umbenennen. Ich würde es so machen, wenn ich wüsste, wie man hinter :name ein Ende für die for-SChleife einfügt.

Die For-Schleife nimmt ja jeden Datei-Namen und gibt sie über %1 an die Befehle set und ren weiter und danach sollte die nächste Datei ran kommen, aber das gesammte Programm läuft so durch. Das sieht man daran, dass immer en Pause gefragt wird.
Und genau deswegen darf ich das nicht nehmen, weil ja später noch mehr kommt.
 
Ok, das ist die Ausgabe ohne den Befehls-Zeilen:

Code:
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Drücken Sie eine beliebige Taste . . .

Die sagt ja eigendlich nur, dass der Dateiname schon existiert und das ist ja auch richtig. Das Programm benennt ja vorher eine Datei so und sollte dann eigendlich weiter zählen und die nächste Datei anders benennen.


So, das ist das Programm mit errorleveln:

Code:
@echo off
set zähler=1
if errorlevel 1 goto failset
for /f "tokens=*" %%i in ('dir /b *.jpg') do (
ren "%%i" "%zähler%.jpg"
if errorlevel 1 goto failren
set /a zähler=%zähler% + 1
if errorlevel 1 goto failzähler
)
if errorlevel 1 goto failfor
pause

:failset
echo Folgender Befehl enthält den Fehler:
echo set zähler=1
goto end
:failren
echo Folgender Befehl enthält den Fehler:
echo ren "%%i" "%zähler%.jpg"
goto end
:failzähler
echo Folgender Befehl enthält den Fehler:
echo set /a zähler=%zähler% + 1
goto end
:failfor
echo die For-Schleife enthält den Fehler.

:end
pause

Das ist die Ausgabe:

Code:
Dateiname existiert bereits, oder die Datei
konnte nicht gefunden werden.
Folgender Befehl enthõlt den Fehler:
ren "%i" "2.jpg"
Drücken Sie eine beliebige Taste . . .

Sie sagt mir nur, dass der ren-Befehl einen Fehler enthält.
Aber das wusste ich auch vorher. Schließlich ist es der ren-Befehl, der den Fehler findet. ER soll ja eine zweite Datei in 1.jpg umbenennen, die aber schon existiert.
Und die 1 wird wiederum von der set-Zeile fest gelegt und die zeigt keinen Fehler an.
 
Ich habe Neuigkeiten.

Mein ursprüngliches Problem ist gelöst.

Und zwar scheint er das alles zu akzeptieren, wenn ich den Wert mit call :sprungziel %%i weiterleite und verarbeite.
Aber wenn ich das so mache, muss der Teil des Programmes, der das verarbeitet am Ende stehen. Das heist, danach muss das Programm zuende sein. Kein exit, oder sonst was.
Denn alles, was danach noch kommt, wird in die For-Schleife mit eingefasst. Ist ja eigendlich auch logisch, aber wie beendet man den Teil, der zur SChleife gehört? Das hab ich noch nicht hingekriegt.

Zumindest werd ich dann später noch mal alles posten und erklären, was ich geändert habe, aber vorher hab ich noch den Programm-Teil:

Code:
::@echo off
dir /b /s |find /v /c "::" > zahl.txt
for /f %%i in (zahl.txt) do set zahl=%%i
del zahl.txt
set /a zahl=%zahl%-2
pause


set zähler=1
for /f %%j in ('dir /b *.jpg') do call :name %%j

:name
if exit %zähler%.jpg (
  set /a zähler=%zähler%+1
) 
if not exit "%zähler%.jpg"(
  set /a zähler=%zähler%+1
  ren "%1" "%zähler%.jpg"
)

Und das gibt er aus:

Code:
J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>dir /b /s   | find /v /c "::"  1>zahl.txt

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>for /F %i in (zahl.txt) do set zahl=%i

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>set zahl=71

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>del zahl.txt

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>set /a zahl=71-2

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>pause
Drücken Sie eine beliebige Taste . . .

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>set zõhler=1

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>for /F %j in ('dir /b *.jpg') do call :name %j

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>call :name 2-1.jpg
"1.jpg" kann syntaktisch an dieser Stelle nicht verarbeitet werden.

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>if exit 1.jpg (

J:\Batch-Projekte\Hintergrund automatisch wechseln\Hintergrundbilder>

"1.jpg" kann syntaktisch an dieser Stelle nicht verarbeitet werden.

Ich versteh einfach nicht, warum. Ich hab doch eigendlich alles richtig gemacht, oder?
Der Teil, zu dem call springt ist auch brav am Ende vom Programm, ic hab also irgendwas anderes falsch gemacht, aber was?
 
Kann mir jemand sagen, wie man %%i in eine Datei schreiben kann?

Code:
echo %%i > x.txt

Ist klar, da wird dann %i geschrieben, ich will aber zwei mal %

Wenn ich ^%^%i schreibe, kommt nur i raus

Denn eventuell hab ich eine Lösung. Und zwar lass ich die beiden For-Schleifen, die folgendes tun sollen:
1. Verhindern, dass Datein doppelt geschrieben werden
2. Die von 1. veränderten Namen einfach durchnummerieren
einfach in eine extra bat schreiben, starte sie dann an der benötigten Stelle und lösche sie danach wieder.

Aber dafür muss das %%i in die bat-Datei geschrieben werden.


----------


Ich hatte eben auch eine andere Lösung:

Code:
@echo off

dir /b /s |find /v /c "::" > zahl.txt
for /f %%i in (zahl.txt) do set zahl=%%i
del zahl.txt
set /a zahl=%zahl%-2

set work=1
:work
if exist %work%*.jpg (
    set /a work=%work%+1
    goto work
) else (
    goto a
)


:a
set zähler=1
for /f "delims=" %%i in ('dir /b *.jpg') do call :name "%%i"
goto :EOF

:name
ren %1 "%work%-%zähler%.jpg"
ren "%work%-%zähler%.jpg" "%zähler%.jpg"
set /a zähler=%zähler%+1

Allerdings wird das dadurch ziemilch instabil.
Wenn dann z.B. schon eine Datei mit dem Namen 25.jpg vorhanden ist, dann greift der Schutz vor dem doppelt schreiben nicht vollständig.

Es kommt also immer mal wieder vor, dass eine Datei schon vorhanden ist, was bedeutet, dass diese Datei nicht ordendlich nummeriert wird.




Außerdem hab ich dabei noch ein anderes Phänomen beobachtet:

Manchmal erstellt das Programm eine Datei, die angeblich nicht vorhanden ist. Ich kann sie nicht löschen, aber der Batch-Script erfasst sie mit, was dann auch wieder zu Problemen führt, da sie ja eigendlich nicht existiert.
Dann ist wieder unsauber nummeriert.

Weis jemand, wie das zustande kommt und was ich dagegen tun kann?
 
Kann mir jemand sagen, wie man %%i in eine Datei schreiben kann?
echo %%i > x.txt
Ist klar, da wird dann %i geschrieben, ich will aber zwei mal %
Komische Sache ist das, keine Ahnung, ob es da Unterschiede von XP Professional (ich) und Windows 7 (du) gibt.

Wenn ich hier in der CMD-Konsole echo %%i > x.txt eingebe, wird auch %%i in die Datei geschrieben, obwohl es ja eine Variable ist.
Richtig wäre das, was du schreibst, also %i.

Derselbe Befehl in der Take Command Console/LE wird richtig behandelt, das heißt, das Sonderzeichen % muss doppelt angegeben werden, damit seine eigentliche Bedeutung aufgehoben wird.
Daraus ergibt sich die Eingabe echo %%%%i > x.txt, also 4 x %, was in TCC/LE zum korrekten Eintrag %%i führt.

Probiere mal bei dir letzteres mit 4 x % aus, das sollte eigentlich so funktionieren.


Manchmal erstellt das Programm eine Datei, die angeblich nicht vorhanden ist. Ich kann sie nicht löschen,...
Solche bockigen Dateien lassen sich mit diesem Tipp entfernen:
Dateien mit reservierten Namen löschen
Funktioniert auch für (leere) Verzeichnisse.
 
Dann pass auf, dass du dir jetzt nicht noch zu viele Prozente rein ziehst! :saufduo
Sowas echo %%%%%%%%%%%%%%%%%%%%i > x.txt solltest du jetzt sein lassen. :ROFLMAO:
 
Ja, das könnte Chaos geben^^

Zumindest fnktionierts jetzt:

Code:
@echo off

dir /b /s |find /v /c "::" > zahl.txt
for /f %%i in (zahl.txt) do set zahl=%%i
del zahl.txt
set /a zahl=%zahl%-2

set work=1
:work
if exist %work%-*.jpg (
    set /a work=%work%+1
    goto work
) else (
    goto a
)


:a

echo set zähler=1 >> name.bat
echo for /f "delims=" %%%%i in ('dir /b *.jpg') do call :name "%%%%i" >> name.bat
echo goto :EOF >> name.bat
echo :name >> name.bat
echo ren %%1 "%%work%%-%%zähler%%.jpg" >> name.bat
echo set /a zähler=%%zähler%%+1 >> name.bat
call name.bat
del name.bat

echo set zähler=1 >> name1.bat
echo for /f "delims=" %%%%j in ('dir /b *.jpg') do call :name1 "%%%%j" >> name1.bat
echo goto :EOF >> name1.bat
echo :name1 >> name1.bat
echo ren "%%work%%-%%zähler%%.jpg" "%%zähler%%.jpg" >> name1.bat
echo set /a zähler=%%zähler%%+1 >> name1.bat
call name1.bat
del name1.bat


Jetzt muss ich noch diese Zeile dort einfügen, wo die lehre Datei erstellt wird:

Code:
del \\.\c:\irgendwo\LPT1

Damit auch dieser Fehler garantiert ausgemerzt ist.


Und dann kann ich den Teil anbauen, der jeden Neustart zählt und die gewählte Datei in die Regestrie schreibt.

Endlich^^


Ach ja, kannst du mir hoffendlich nur einmal zu dem Thema helfen?


Den Code hattest du mir ja gegeben:

Code:
set wallpaper="G:\User\[Name]\Pictures\Wallpaper\%num%.jpg"
REG ADD "HKCU\Control Panel\Desktop" /V Wallpaper /T REG_SZ /F /D "%wallpaper%"
%SystemRoot%\System32\RUNDLL32.EXE user32.dll, UpdatePerUserSystemParameters

Der funktioniert auch wunderbar, aber wie kann ich dann auch gleich die Bilder gestreckt einfügen lassen?
Oder die anderen EInstellungen? Ich weis, dass das in der Registry steht, aber nicht wo.

Außerdem wollte ich dich noch das zum reg-Befehl fragen:

HKLM - HKEY_LOCAL_MACHINE
HKCU - HKEY_CURRENT_USER
HKCR - HKEY_CLASSES_ROOT
HKU - HKEY_USERS
HKCC - HKEY_CURRENT_CONFIG

Stimmt die Zuordnung der Stammschlüssel?


Edit:
Gute Nacht, ich hau mich jetzt hin. :sleep Sonst übersteh ich den Tag morgen nicht. :schlaf
 
Zuletzt bearbeitet:
Oben