UDF - _FileRename

  • Hi,

    hiermit präsentiere ich Euch die UDF _FileRename. Durch den DOS-Befehl soll das Umbenennen bei großen Dateien im Vergleich zu FileMove deutlich schneller sein. Dies habe ich jedoch nicht ausprobiert. Siehe dazu auch: http://www.autoitscript.com/forum/index.php?showtopic=70058

    Spoiler anzeigen
    [autoit]

    ;===============================================================================
    ; Function Name.....: _FileRename
    ; Description.......: Renames a file using the command "rename".
    ; Version...........: 1.0.4
    ; Change Date.......: 2008-07-29
    ; AutoIt Version....: 3.2.12.1
    ;
    ; Parameter(s)......: $S_FILE - String containing the directory or file to rename.
    ; $S_RENAME - String containing the new name of the file, without the path.
    ; Requirements(s)...: None
    ; Return Value(s)...: Success: Returns the exit code of the "rename" command.
    ; Failure: Returns 0 and sets @error to:
    ; 1 = The file or folder $S_FILE does not exist.
    ; 2 = $S_RENAME is an invalid filename.
    ;
    ; Author(s).........: xVivoCity
    ; Modified by: JellyFish666 & litlmike
    ; Modified by: teh_hahn <[email='sPiTsHiT@gmx.de'][/email]>
    ; Company...........: None
    ; URL...............: None
    ; Note(s)...........: None
    ;===============================================================================
    Func _FileRename(Const $S_FILE, Const $S_RENAME)
    If Not FileExists($S_FILE) Then Return SetError(1, 0, 0)
    If Not StringRegExp($S_RENAME, '(?i)^[^<>\?":\|\\/\*]+$') Then Return SetError(2, 0, 0)

    [/autoit] [autoit][/autoit] [autoit]

    Return RunWait(@ComSpec & ' /c ren "' & $S_FILE & '" "' & $S_RENAME & '"', "", @SW_HIDE)
    EndFunc ;==>_FileRename

    [/autoit]

    EDIT: Wie Oscar festgestellt hat, ist diese Funktion doch nicht schneller als FileMove! Aus diesem Grund hier eine modifizierte Version mit FileMove:

    Spoiler anzeigen
    [autoit]

    ;===============================================================================
    ; Function Name.....: _FileRename
    ; Description.......: Renames a file.
    ; Version...........: 1.0.5
    ; Change Date.......: 2008-08-04
    ; AutoIt Version....: 3.2.12.1
    ;
    ; Parameter(s)......: $S_SOURCE - String containing the source path and filename of the file to rename.
    ; $S_DEST - String containing the new filename of the file, without the path.
    ; $i_flag - [optional] Integer specifying whether to overwrite a file if it already exist or not:
    ; 0 = (default) Do not overwrite a existing file.
    ; 1 = Overwrite a existing file.
    ; Requirements(s)...: None
    ; Return Value(s)...: Success: Returns 1
    ; Failure: Returns 0 and sets @error to:
    ; 1 = The file or folder $S_SOURCE does not exist.
    ; 2 = $S_DEST is an invalid filename.
    ; 3 = The source file $S_SOURCE cannot be moved or the destination file $S_DEST already exists and the flag $i_flag is set to 0.
    ;
    ; Author(s).........: teh_hahn <[email='sPiTsHiT@gmx.de'][/email]>
    ; Company...........: None
    ; URL...............: None
    ; Note(s)...........: None
    ;===============================================================================
    Func _FileRename(Const $S_SOURCE, Const $S_DEST, $i_flag = 0)
    If Not FileExists($S_SOURCE) Then Return SetError(1, 0, 0)
    If Not StringRegExp($S_DEST, '(?i)^[^<>\?":\|\\/\*]+$') Then Return SetError(2, 0, 0)
    If $i_flag <> 1 Then $i_flag = 0
    If Not FileMove($S_SOURCE, StringLeft($S_SOURCE, StringInStr($S_SOURCE, "\", 0, -1) - 1) & "\" & $S_DEST, $i_flag) Then Return SetError(3, 0, 0)
    EndFunc ;==>_FileRename

    [/autoit]

    2 Mal editiert, zuletzt von teh_hahn (4. August 2008 um 10:58)

  • Sicher, eigentlich ist es nur eine Zeile. Aber ich denke trotzdem, dass es der Eine oder Andere gebrauchen kann. Und das Error Handling ist jawohl obligatorisch, ich würde bei mehrmaliger Verwendung von Umbenennungen nicht immer auf eine kopierte Zeile vertrauen. Damit geht ja jede Wartbarkeit des Codes verloren...

    • Offizieller Beitrag

    Ich habe mal den Test gemacht mit einer 1GB großen Datei. FileMove() ist schneller.

    Und weil es mich mal interessiert hat, habe ich eine WMI-Variante geschrieben:

    [autoit]


    Func _WMIFileRename($sCurrentFile, $sNewFile)
    Local $objWMI, $objFile, $sCurrentFilePath, $sNewFilePath, $rc
    If Not FileExists($sCurrentFile) Then Return SetError(1, 0, 0)
    If FileExists($sNewFile) Then Return SetError(2, 0, 0)
    $objWMI = ObjGet("winmgmts:\\.\root\cimv2")
    $objFile = $objWMI.Get("Cim_Datafile='" & $sCurrentFile & "'")
    $sCurrentFilePath = Stringleft($sCurrentFile, StringInStr($sCurrentFile, "\", 0, -1))
    If $sCurrentFilePath = "" Then $sCurrentFilePath = @ScriptDir & "\"
    $sNewFilePath = Stringleft($sNewFile, StringInStr($sNewFile, "\", 0, -1))
    $sNewFile = StringMid($sNewFile, StringInStr($sNewFile, "\", 0, -1) + 1)
    If $sNewFilePath = "" Then $sNewFilePath = $sCurrentFilePath
    $rc = $objFile.Rename($sNewFilePath & $sNewFile)
    If $rc <> 0 Then Return SetError(3, 0, 0)
    $objWMI = 0
    Return $sNewFilePath & $sNewFile
    EndFunc

    [/autoit]

    Aber die ist sehr viel langsamer als FileMove(). :S

  • Hi,
    alles klar! Dann hatte der Herr im englischen Forum wohl Unrecht. Dann die Funktion besser nicht verwenden und auf FileMove zurückgreifen. Habe das im ersten Post dieses Threads mal angepasst!

    • Offizieller Beitrag

    Kannst ja mal die Geschwindigkeit testen bei Umbenennen mit FileSystem Object:

    [autoit]

    Func _FSOFileRename($sCurrFilePath, $sNewName)
    If Not FileExists($sCurrFilePath) Then Return SetError(1,0,1)
    Local $oFSO = ObjCreate('Scripting.FileSystemObject')
    $oFSO.MoveFile($sCurrFilePath, $sNewName)
    EndFunc

    [/autoit]
    • Offizieller Beitrag

    Hier noch ein Nachtrag:

    Die FileSystemObject-Variante ist etwas schneller als die FileMove()-Variante, wenn man das Objekt außerhalb der Funktion erstellt (z.B. weil man mehrere Dateien umbenennen will):

    [autoit]


    Global $oFSO = ObjCreate('Scripting.FileSystemObject')

    [/autoit][autoit][/autoit][autoit]

    Func _FSOFileRename($sCurrFilePath, $sNewName)
    If Not FileExists($sCurrFilePath) Then Return SetError(1,0,1)
    $oFSO.MoveFile($sCurrFilePath, $sNewName)
    EndFunc

    [/autoit]

    Für das umbenennen mehrerer Dateien ist diese Funktion also die Schnellste.

    Man kann die Funktion auch so schreiben:

    [autoit]


    Func _FSOFileRename($sCurrFilePath, $sNewName)
    If Not FileExists($sCurrFilePath) Then Return SetError(1,0,1)
    Local $file = $oFSO.GetFile($sCurrFilePath)
    $file.Name = $sNewName
    EndFunc

    [/autoit]


    Dann darf die Variable $sNewName allerdings nur den neuen Dateinamen (ohne Pfad) enthalten.