In einen einzeiligen Befehl konvertiertes mehrzeiliges Stapelskript gibt andere Ergebnisse als das Original zurück

1

Ich versuche, das mehrzeilige Skript zu transformieren

@echo off

for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (
  pushd "%%D"
  for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul
  popd
  rd /s /q "%%D"
)
exit

in eine einzelne Zeile, um sie als Kontextmenüeintrag zu registrieren. Nach meinem Verständnis wäre der entsprechende einzeilige Befehl der folgende:

@echo off && for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (pushd "%%D" && for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul && popd && rd /s /q "%%D") && exit

... aber es erzeugt andere Ergebnisse als das ursprüngliche Skript.

Das Ersetzen von && durch & ergibt ein drittes anderes Ergebnis, aber meines Wissens würde ich in diesem Fall trotzdem das && brauchen.

Was könnte ich falsch machen?

Jesús Cruz
quelle
Dies ist nur eine Vermutung, &&bedeutet aber , dass der Befehl nur ausgeführt wird, wenn der vorherige erfolgreich war. Es könnte Züge geben, die in der inneren Schleife scheitern? Sie können nur &die Befehle aneinanderreihen.
ernie
Versuchte das auch schon, aber es hat auch nicht funktioniert. Es ist jedoch sinnvoll zu warten, bis der vorherige Befehl beendet ist. Soweit ich weiß, fungiert jeder Zeilenumbruch in diesem Sinne als &&, daher sollte er grundsätzlich gleich sein. Ich habe mich jedoch geirrt und musste fragen.
Jesús Cruz
2
Alternativ können Sie dies möglicherweise in einer Batch-Datei speichern und das Batch-Skript von Ihrem Kontextmenüeintrag aufrufen lassen.
ernie
1
Das ist der Backup-Plan, aber ich möchte lieber unnötige Dateien und absolute Pfade vermeiden.
Jesús Cruz
1
Ich frage mich, ob die öffnende und schließende Klammer des DOTeils der FOR-Schleife nicht glücklich ist, durch getrennt zu werden &&. Auch das Eröffnungsecho aus und die abschließenden Exit-Anweisungen sind wahrscheinlich nicht erforderlich.
Twisty Imitator

Antworten:

1

Es stellt sich heraus, dass for … does "gierig" ist. (Ich erinnere mich nicht, dass ich das vorher gewusst habe, und es scheint nicht prominent dokumentiert zu sein for /?.)

Folgendes meine ich:

Betrachten Sie Skript cow1.bat:

@echo off
for %%a in (how now brown) do echo %%a
echo cow

Ziemlich trivial. Beim Ausführen wird ausgegeben

how
now
brown
cow

wie wir vermuten könnten.

Betrachten Sie Skript cow2.bat:

@echo off
for %%a in (how now brown) do echo %%a & echo cow

Das Gleiche, mit Ausnahme der Zeilen 2 und 3, die durch a getrennt sind &. Erraten Sie, was!? Beim Ausführen wird ausgegeben

how
cow
now
cow
brown
cow

Es wird so interpretiert, als ob es wäre

@echo off
for %%a in (how now brown) do (echo %%a & echo cow)

(Der Wechsel &zu &&hatte keine Wirkung.) In einer (für mich) größeren Überraschung,

@echo off
for %%a in (how now brown) do (echo %%a) & echo cow

auch funktioniert genauso wie cow2. Ich musste verwenden

@echo off
(for %%a in (how now brown) do echo %%a) & echo cow

um das Original zu erhalten, cow1Verhalten.


Wie wirkt sich das auf das OP aus?

for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul && popd && rd /s /q "%%D"

ist analog zu cow2: Wenn %%D(das Verzeichnis, in das wir gerade pushdgegangen sind) beatles, dann tut das obige Codesegment dies:

move "george" "..\beatles - george" >nul    &&    popd    &&    rd /s /q "beatles"
move "john"   "..\beatles - john"   >nul    &&    popd    &&    rd /s /q "beatles"
move "paul"   "..\beatles - paul"   >nul    &&    popd    &&    rd /s /q "beatles"
move "ringo"  "..\beatles - ringo"  >nul    &&    popd    &&    rd /s /q "beatles"

(Leerzeichen zur Verdeutlichung hinzugefügt). So bewegt es die erste Datei ( george) und dann popd‚ing aus dem beatlesVerzeichnis und löscht es, die anderen Dateien zu verlassen durch die roomba geerntet werden.

Empfehlung (TL; DR)

Versuchen

for / f "eol =: delims =" %% D in ('dir / b / s / ad * ^ | sort / r') do (pushd "%% D" && ( für %% F in (*) do verschiebe "%% F" ".. \ %% ~ nxD - %% F"> nul ) && popd && rd / s / q "%% D")
                                                                              ↑ ↑
 

Triviale Frage:

Warum brauchen wir das *im dir /b /s /ad *Unterbefehl?

G-Man
quelle
Ich werde dies nicht als Entschuldigung verwenden, aber ich habe dieses Skript auf Anfrage erhalten, da ich bisher nicht herausgefunden habe, wo ich es lernen kann. Ich fürchte, ich kann diese Frage nicht beantworten. Ich würde wirklich gerne den Code lernen oder zumindest verstehen, den ich erhalten habe, aber er ist sinnlos, ohne das Grundwissen, das ich vermisse.
Jesús Cruz
"Warum brauchen wir das *im dir /b /s /ad *Unterbefehl?" Das tust du nicht.
DavidPostill
@ JesúsCruz: Nun, versuchen Sie laufen dir /b /s /ad *und dir /b /s /adzu verschiedenen Zeiten an verschiedenen Orten, Situationen und Kontexten. Wenn sie immer die gleiche Ausgabe produzieren, können Sie sicher sein, dass David und ich Recht haben und dass sie gleichwertig sind. Wenn Sie fett sind, können Sie die überflüssigen zwei Zeichen aus Ihrem Skript löschen. Wenn Sie jedoch jemals unterschiedliche Ausgaben von den beiden Befehlen erhalten, kehren Sie bitte hierher zurück und lassen Sie es uns wissen, denn dann haben Sie uns etwas beigebracht.
G-Man
Ich werde es entfernen und sehen, ob etwas nicht mehr funktioniert. Eine weitere Frage, auch wenn sie nicht zum Thema gehört (ich weiß nicht, ob es sich lohnt, ein neues Thema zu eröffnen): Das Skript funktioniert nicht mit Ordnern, deren Dateinamen mit 'gekennzeichnet sind. Irgendeine Idee warum?
Jesús Cruz
Eigentlich funktioniert das Skript, nachdem ich das * entfernt habe, mit einfachen Anführungszeichen in Dateinamen. Danke für alles.
Jesús Cruz