merkwürdiges Verhalten bei DirMove

    • Offizieller Beitrag

    Ich bin gerade auf ein merkwürdiges Verhalten von DirMove gestossen.

    Vorab die Testumgebung:

    Quellverzeichnis ist: $sSource = 'd:\Quelle'

    Zielverzeichnis ist: $sDest = 'd:\Ziel'

    Punkt 1: Führe ich nun ein DirMove($sSource, $sDest, 0) aus, also mit 0 = $FC_NOOVERWRITE, dann passiert gar nichts! Das Verzeichnis "Quelle" wird nicht verschoben, obwohl es nicht im Zielverzeichnis vorhanden ist.

    Ein DirMove($sSource, $sDest, 1) mit 1 = $FC_OVERWRITE, verschiebt das Verzeichnis hingegen in das Zielverzeichnis.

    Punkt 2: Aber, und jetzt wird es total kurios, führe ich DirMove($sSource, $sDest, 1) nochmal aus (also mit bereits existierendem Verzeichnis "Quelle" im Zielverzeichnis, so werden nicht die Dateien in "D:\Ziel\Quelle" überschrieben, sondern das Quelle-Verzeichnis wird nach "D:\Ziel\Quelle" verschoben. Es existiert dann "D:\Ziel\Quelle\Quelle" mit den Dateien aus "D:\Quelle".

    Ok, in der Hilfe zu DIrMove steht Punkt 2 so geschrieben: "If the destination already exists and the overwrite flag is specified then the source directory will be moved inside the destination."

    Aber das ist doch völlig absurd! Ich will doch lediglich, dass das Verzeichnis "Quelle" nach "Ziel" verschoben wird und dabei ein bereits vorhandenes "Quelle" überschrieben wird.

    Muss ich dazu wirklich alle Dateien einzeln verschieben (mit FileMove)?

    Oder habe ich etwas übersehen?

  • Hallo Oscar !

    Ich gehe mal schrittweise vor, sonst ist z.B. alpines schon wieder fertig bevor ich gepostet habe :P

    Punkt 1: Führe ich nun ein DirMove($sSource, $sDest, 0) aus, also mit 0 = $FC_NOOVERWRITE, dann passiert gar nichts!

    ; Quellverzeichnis :

    Global $sSourceDir = 'd:\SourceDir'

    ; Zielverzeichnis :

    Global $sDestinationDir = 'd:\DestDir'

    ; Test 1 :

    ; =================

    If DirMove($sSourceDir, $sDestinationDir, $FC_NOOVERWRITE) Then

    ConsoleWrite('Verzeichnis = ' & $sSourceDir & ' erfolgreich verschoben ' & @CRLF)

    Else

    ConsoleWrite('Verzeichnis = ' & $sSourceDir & ' - Fehler bei DirMove ' & @CRLF)

    EndIf

    Ergebnis (das sieht bei mir schon mal anders aus) :

    - Falls $sDestinationDir nicht bereits existiert, dann wird $sSourceDir gelöscht und die Dateien stehen in $sDestinationDir.

    DirMove arbeitet quasi nur wie ein DirRename. Es entsteht keine Struktur d:\DestDir\SourceDir

    - Existiert hingegen $sDestinationDir (auch wenn leer), dann schlägt DirMove fehl (hier greift $FC_NOOVERWRITE).

    Test 2 : wie Test 1 , aber mit $FC_OVERWRITE :

    Hierbei wird d:\SourceDir gelöscht, und unter d:\DestDir wird (als Unterverzeichnis) \SourceDir angelegt.


    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    2 Mal editiert, zuletzt von Musashi (12. Oktober 2017 um 09:20) aus folgendem Grund: erweitert

  • Ich kann das Verhalten reproduzieren.

    Vielleicht nochmal zusammengefasst was passiert:

    • 'd:\Quelle' existiert
      'd:\Ziel\Quelle' existiert noch nicht
    • DirMove('d:\Quelle', 'd:\Ziel\Quelle', 0) -> Verzeichnis 'd:\Ziel\Quelle' existiert nun und ist korrekt gefüllt.
    • 'd:\Quelle' wird wieder befüllt
    • DirMove('d:\Quelle', 'd:\Ziel\Quelle', 1) -> nun existiert ein Unterordner 'd:\Ziel\Quelle\Quelle' - dieser wird gleich mal gelöscht
    • 'd:\Quelle' wird wieder befüllt
    • DirMove('d:\Quelle', 'd:\Ziel', 1) -> es wird wieder der Unterordner 'd:\Ziel\Quelle\Quelle' erstellt!

    Für mich riecht das streng nach Bug.
    Da ich mit _WinAPI_MoveFileEx() auch keine zufriedenstellenden Ergebnisse produzieren konnte würde ich für's erste auf Run-Aufrufe von robocopy ausweichen (das arbeitet eh inkrementell und sollte daher die flottere Alternative sein).

    • Offizieller Beitrag

    - Existiert hingegen $sDestinationDir (auch wenn leer), dann schlägt DirMove fehl (hier greift $FC_NOOVERWRITE).

    Achso!

    Ich muss als Ziel dann "D:\Ziel\Quelle" angeben. Ok, so funktioniert es zumindest mit $FC_NOOVERWRITE.

    Aber mit $FC_OVERWRITE werden nicht die Dateien in "D:\Ziel\Quelle" überschrieben, sondern es wird noch ein Unterverzeichnis erstellt und die Dateien dort hinein verschoben.

    Ich müsste also vorher ein evtl. existierendes Verzeichnis löschen.

  • Ich müsste also vorher ein evtl. existierendes Verzeichnis löschen.

    Was aber dann Probleme bringt wenn im Zielverzeichnis Daten liegen die nicht im Quellverzeichnis liegen.
    Man will ja eigentlich dass das Zielverzeichnis mit dem Inhalt vom Quellverzeichnis aktualisiert wird.

    Als Beispiel:
    In Quelle liegen: A.txt, B.txt

    In Ziel liegen: A.txt, B.txt, C.txt

    Ein Dirmove sollte nun A.txt und B.txt überschreiben und dabei C.txt erhalten.

    Würde man vorher immer erst das Zielverzeichnis löschen wäre C.txt hinüber.

    • Offizieller Beitrag

    Ah, es gibt einen WinAPI-Befehl der das macht, was ich mir vorstelle: _WinAPI_ShellFileOperation

    Und zwar so:

    AutoIt
    #include <WinAPIShellEx.au3>
    $sSource = 'd:\Quelle'
    $sDest = 'd:\Ziel'
    _WinAPI_ShellFileOperation($sSource, $sDest, $FO_MOVE, $FOF_NOCONFIRMATION)

    Und mit "0" statt $FOF_NOCONFIRMATION kommt sogar noch eine Nachfrage, was geschehen soll.

    Ich habe also einen Workaround gefunden, aber das Verhalten von DirMove empfinde ich trotzdem als fehlerhaft.

  • 'd:\Quelle' existiert
    'd:\Ziel\Quelle' existiert noch nicht

    Das ist aber nicht die Ausgangslage, wie Oscar sie oben beschrieben hat ! Dort heißt es :

    Vorab die Testumgebung:

    Quellverzeichnis ist: $sSource = 'd:\Quelle'

    Zielverzeichnis ist: $sDest = 'd:\Ziel'

    Falls man die Quelle wieder befüllt, dann verhält es sich so wie AspirinJunkie beschreibt :

    Ein DirMove erzeugt ein weiteres Unterverzeichnis, hier also d:\DestDir\SourceDir\SourceDir

    Macht man das 10x , dann erhält man die Struktur : d:\DestDir\SourceDir\SourceDir\SourceDir\SourceDir\SourceDir\ usw.

    Meiner Meinung nach definitiv nicht das gewünschte Verhalten !!

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    • Offizieller Beitrag

    Ein Dirmove sollte nun A.txt und B.txt überschreiben und dabei C.txt erhalten.

    Würde man vorher immer erst das Zielverzeichnis löschen wäre C.txt hinüber.

    Stimmt, somit fällt das vorherige löschen des Verzeichnisses aus.

    Aber, wie in Post#6 beschrieben, gibt es zumindest eine andere Möglichkeit.

  • Das ist aber nicht die Ausgangslage, wie Oscar sie oben beschrieben hat !

    Korrekt - ich wollte lediglich ein nachvollziehbares Beispiel basteln damit jeder andere schnell probieren kann ob DirMove bei ihm auch diesen Knacks hat.

    Edit: Wurde schon vor 8 Jahren berichtet aber als kein Bug abgetan (für mich nicht nachvollziehbar): >>https://www.autoitscript.com/trac/autoit/ticket/1543<<

    Einmal editiert, zuletzt von AspirinJunkie (12. Oktober 2017 um 09:55)

  • Hallo AspirinJunkie !

    Korrekt - ich wollte lediglich ein nachvollziehbares Beispiel basteln damit jeder andere schnell probieren kann ob DirMove bei ihm auch diesen Knacks hat.

    War auch überhaupt nicht als Kritik gemeint ;)

    Das missverständliche Verhalten besteht, noch mal kurz zusammengefasst, darin :

    Habe ich z.B. ein Verzeichnis d:\Quelle und möchte dieses Verzeichnis per DirMove nach d:\Ziel verschieben, dann erwartet man als Ergebnis :

    ==> Flag $FC_OVERWRITE ist gesetzt (sonst arbeitet DirMove ja wie ein Rename, falls d:\Ziel nicht existiert)

    -> d:\Quelle wird entfernt

    -> unter d:\Ziel gibt es jetzt das Verzeichnis \Quelle, also der komplette Pfad lautet : d:\Ziel\Quelle

    Wiederholt man den Vorgang, d.h. d:\Quelle wurde erneut befüllt und verschoben, dann erwartet man :

    -> d:\Quelle wird entfernt

    -> in d:\Ziel\Quelle werden die Daten aktualisiert, d.h. existierende Dateien werden überschrieben, Neue hinzugefügt

    Was aber passiert ist : Es wird ein neues Verzeichnis \Quelle hinzugefügt, also d:\Ziel\Quelle\Quelle [ad infinitum]

    Na ja, Oscar hat ja bereits einen eleganten work-around gefunden ^^

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    Einmal editiert, zuletzt von Musashi (12. Oktober 2017 um 13:30) aus folgendem Grund: Tippfehler FileMove statt DirMove

    • Offizieller Beitrag

    Edit: Wurde schon vor 8 Jahren berichtet aber als kein Bug abgetan (für mich nicht nachvollziehbar):

    Das kann ich auch nicht nachvollziehen!

    Vor allem, weil DirCopy diesen "Fehler" eben nicht macht.

    Ein weiterer Workaround wäre demnach: erst DirCopy und dann (bei erfolgreichen DirCopy) DirRemove.

    So, wie er momentan funktioniert, kann man von DirMove jedenfalls nur abraten.

  • Im Prinzip ist eigentlich alles bereits gesagt !;)

    Da es sich bei DirMove aber um eine gebräuchliche Standardfunktion handelt, möchte ich trotzdem noch einen Kommentar abgeben.

    In den Hilfen steht :

    "If the destination already exists and the overwrite flag is specified then the source directory will be moved inside the destination."

    bzw. :

    "Wenn der Zielort schon existiert, und bei "flag" angegeben wird, dass überschrieben werden soll, so wird das Quellverzeichnis in das Zielverzeichnis verschoben."

    Die Verwendung von Fettschrift bei den Worten inside bzw. in , ist meiner Meinung nach nicht ausreichend !

    Ich kann mir kaum vorstellen, dass ein Normaluser daraus das in diesem Thread beschriebene Funktionsverhalten ableiten kann.

    Wurde schon vor 8 Jahren berichtet aber als kein Bug abgetan (für mich nicht nachvollziehbar): >>https://www.autoitscript.com/trac/autoit/ticket/1543<<

    Volle Zustimmung bzgl. 'nicht nachvollziehbar' !

    In der Begründung, dies nicht als Fehler zu werten, steht (Zitat) :

    "I know it can be seen as funny but it was a old time design decision" (funny meint hier wohl 'seltsam' und hoffentlich nicht 'lustig/witzig')

    auf Deutsch : "Ich weiß, es kann als seltsam betrachtet werden, aber es handelt sich um eine lang zurückliegende Planungsentscheidung"

    Ein etwas verbohrter Standpunkt, wenn ihr mich fragt !

    Die Sache geht sogar noch weiter zurück. Bereits 2006 (also vor 11 Jahren !!) entstand folgender Thread :

    https://www.autoitscript.com/forum/topic/37…nd-directories/
    Auch hier brachte der User 'The Kandie Man' bereits sein Unverständnis zum Ausdruck und schlug vor,

    einen weiteren Parameter einzufügen, der das einfache Überschreiben des Zielverzeichnisses erlaubt.

    Sein work-around entsprach dem von Oscar, also die Variante :

    $source = 'C:\test1'

    $dest = 'C:\test2'

    If DirCopy($source,$dest,1) Then DirRemove($source,1)

    So, wie er momentan funktioniert, kann man von DirMove jedenfalls nur abraten.

    Daher mein Vorschlag (auch an Tweaky ) :

    Ich halte es aufgrund der relativen Bedeutung dieser Funktion für sinnvoll, die deutsche Hilfe zu erweitern, d.h. :

    - deutlicher auf das beschriebene Funktionsverhalten hinzuweisen

    - als Beispiel die von Oscar erstellten work-arounds einzufügen

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Der Thread ist ja schon älter, aber da Musashi diesen gerade verlinkt hat habe ich Ihn mir mal angesehen und bin ein wenig verwundert:

    Um die Betrachtung zu vervollständigen: Betriebssystem = xp Sp3 32bit. Nicht dass der Fehler noch Systemabhängig ist.

    Oscar schreibt:

    Vorab die Testumgebung:

    Quellverzeichnis ist: $sSource = 'd:\Quelle'

    Zielverzeichnis ist: $sDest = 'd:\Ziel'

    Punkt 1: Führe ich nun ein DirMove($sSource, $sDest, 0) aus, also mit 0 = $FC_NOOVERWRITE, dann passiert gar nichts! Das Verzeichnis "Quelle" wird nicht verschoben, obwohl es nicht im Zielverzeichnis vorhanden ist.

    ------------------

    Das kann ich so nachvollziehen. Wenn jedoch die Quelle nicht leer ist.... kommt es noch schlimmer... der Inhalt von Quelle wird verschoben das Verzeichnis Quelle hingegen gelöscht.

    Nach einem :

    $sSource = 'f:\Quelle'

    $sDest = 'f:\Ziel4'

    DirMove($sSource, $sDest, 0)

    Ordner vor dem move:

    F:\Quelle\doc1.txt

    nach dem move:

    F:\Ziel4\doc1.txt und das Verzeichnis Quelle wurde gelöscht...

    ein:

    DirMove($sSource, $sDest, 1) verschiebt das Quelle Verzeichnis sammt Inhalt tatsächlich nach F:\ziel4 (Quelle Verzeichnis hat dort nicht existiert)

    Macht man das ganze nochmal (Quelle Verzeichnis in F:\neu angelegt) wird tatsächlich Quelle nach F:\ziel4\Quelle\Quelle

    verschoben


    Wenn das nicht buggy ist

    Kann man den Machern nicht mal nahelegen sowas zu ändern....


    Gruß

    Peter

    Hinweise auf Suchmaschinen finde ich überflüssig - wer fragt hat es nicht gefunden oder nicht verstanden. Die Antwort gibt sich oftmals schneller als der Hinweis auf Dr. Goggle & Co.

    Ab 19-10-22 ergänzt um:

    Die Welt wird nicht bedroht von den Menschen, die böse sind, sondern von denen, die das Böse zulassen. (Albert Einstein)

    2 Mal editiert, zuletzt von Peter S. Taler (1. Juni 2018 um 19:59)

    • Offizieller Beitrag

    Kann man den Machern nicht mal nahelegen sowas zu ändern....

    Kannst du vergessen. Ich habe den Eindruck, dass Bug-Tickets von vornherein als Akt der Beleidigung aufgefasst werden. Somit versteht sich von selbst, dass nicht ernsthaft ins Auge gefasst wird, etwas zu ändern.

    Ist ja auch frech, dass User sich erdreisten Eure Hoheiten mit so etwas Profanem, wie Bugs zu belästigen. :whistling:

  • BugFix vielleicht fehlt es an der nötigen Demut in den Bugreporten :rofl:

    Im Ernst, es ist schade um eine Sprache wie Autoit, wenn soetwas nicht ausgemerzt wird.

    Ob es Sinn macht wenn man diesen Bug nicht als einzelner meldet sondern als "Forum"?

    Gruß

    Peter

    Hinweise auf Suchmaschinen finde ich überflüssig - wer fragt hat es nicht gefunden oder nicht verstanden. Die Antwort gibt sich oftmals schneller als der Hinweis auf Dr. Goggle & Co.

    Ab 19-10-22 ergänzt um:

    Die Welt wird nicht bedroht von den Menschen, die böse sind, sondern von denen, die das Böse zulassen. (Albert Einstein)

  • Nachdem ich mich im Netz ein wenig umgesehen habe und ich zudem den Gedanken nicht los werde das schon mal bearbeitet zu haben,

    komme ich zu der Ansicht, dass das Problem ev. in der falschen Hilfe Datei liegt und damit ev. in unser aller Verständnis?

    Ich fand z.B. diesen Beitrag:

    You need to specify the full path you want to move the folder to, including the name you want the folder to have in the new location.

    for example: DirMove("C:\SomeFolder\MoveFolder", "C:\SomeOtherFolder") would rename "MoveFolder" to "SomeOtherFolder" which is created in "C:\".

    To Move the folder inside the other folder use:

    DirMove("C:\SomeFolder\MoveFolder", "C:\SomeOtherFolder\MoveFolder")

    -----

    Da Autoit kein rename kennt verwenden wir ja alle filemove zum umbenennen. Unterstellen wir hier eine gewisse Analogie dann macht das fast schon Sinn..

    Peter

    Hinweise auf Suchmaschinen finde ich überflüssig - wer fragt hat es nicht gefunden oder nicht verstanden. Die Antwort gibt sich oftmals schneller als der Hinweis auf Dr. Goggle & Co.

    Ab 19-10-22 ergänzt um:

    Die Welt wird nicht bedroht von den Menschen, die böse sind, sondern von denen, die das Böse zulassen. (Albert Einstein)