Renaming files outside the project via code

Godot Version

4.5

Question

Hi! My application needs to give the user the possibility to rename files created by the application itself in a specific folder. I’ve tried different approaches but none worked:

  • DirAccess.rename_absolute(oldFilePath, newFilePath): this function deletes all other files in the folder except the “renamed” one, which doesn’t get renamed anyway…
  • OS.execute(...): didn’t work and it’s too OS dependent so I would much rather avoid it.
  • DirAccess.copy(old, new) + DirAccess.remove(old): this approach fails at copy with debugger saying it failed accessing all files in the folder.
  • I also tried instantiating the DirAccess through the open() method, then tried the rename() function (same result as rename_absolute()) and also tried copy/remove, which gives the same error as the static functions.

Any idea on how to do this? Do I really have to delve into the OS.execute different OS ways to do stuff? Do I need a C# script to do it? What am I missing?
Thanks in advance for the help :folded_hands:

1 Like

Is that really the case? Can you show code example that demonstrates it?

var dirPath : String = folder_path()
	for row : Control in fileRowsContainer.get_children():
		var old : String = dirPath + row.get_child(0).name
		var new : String = dirPath + row.get_child(0).text
		if old != new:
			DirAccess.rename_absolute(old, new)

fileRowsContainer has 1 Control row children for each file in the folder which has as first child a TextEdit, each TextEdit is setup at first with properties name and text set as the original file name, and when the user closes the UI the code above is triggered to rename when it finds a difference between the 2 properties. The result is what described in the topic: the file is not renamed and all other files in the folder are deleted. Let me know if you need a console output of the filepaths I can provide it (I already tried making it delete the file when TextEdit properties differs and it works correctly so I doubt it’s a path related problem on my end).
Other disclaimers: the names are edited preserving file extension and I have enabled the “show hidden elements” in the file explorer. Searching all the inadvertedly deleted files in the whole filesystem doesn’t find any results.

Your code doesn’t check if a new name is equal to some other existing name in the folder.

Which OS are you doing this on?

I’m using rename() in Stahldrache without seeing this kind of behavior (when I save data I write to a temp file and then rename it over top of the real file once I’m sure it’s fully written and good…).

You may also be getting bitten by new being a keyword. Maybe make it old_name and new_name?

1 Like

DirAccess.rename_absolute() returns an Error. Try printing it:

var error: Error = DirAccess.rename_absolute(from, to)
print(error_string(error))

Even if it fails, there should be no way it deletes any files. If it doesn’t fail and the files are not where they are supposed to be, they got renamed to something you didn’t expect.

@normalized true, but I do :sweat_smile: and I know what the file names are and always pay attention not to call them the same. I will definitely add a check once the basic feature works properly.

@hexgrid Windows 11. I just tried changing variable names but still behaves as described previously, I will keep them with the suffix you suggested for safety tho.

@zigg3c All it prints is Failed. Nothing more, nothing less :smiling_face_with_tear:

1 Like

I wonder if you’re somehow renaming the containing directory or something?

It could also be that it’s a bug in Godot; do you see the same result on a different version?

The most likely culprit is wrong filepaths. That means that whatever paths you are passing to the function are somehow malformed/incorrect. Try printing them out.
The second most likely culprit is something to do with permissions, but we won’t need to get into that before we check the first one.

Do the simplest possible test with known filenames and literal strings. Always do that when things are behaving strange.

2 Likes

Also when assembling paths use String::path_join(). Much safer than using + operator.

EDIT: mistakenly replied to @hexgrid. It’s directed at OP, of course.

1 Like
var dirPath : String = folder_path()
    # ...
		var old : String = dirPath + row.get_child(0).name
		var new : String = dirPath + row.get_child(0).text
        # ...
  • Does dirPath end with a path delimiter character?
  • Are you certain that it is an absolute path?

Always print every relevant variable every step of the way.

It’s the most fundamental debugging tool. I’m baffled at how many people present their “mysterious” bugs here without ever trying to do that.

2 Likes

Yup. Or in this case: set a breakpoint and use the debugger.

1 Like

I found the problem, you’re all right it’s the paths. I did print them before, but I also did miss the problem with it (I’ve been working on fixing this for the past 2 days, I’ve got logs everywhere, meaning too many). When assigning the old filename to the TextEdit name property the extension . is changed to _ by Godot itself, therefore the rename fails because it cannot find the original file to rename. I removed the file extension from TextEdit name and text properties, adding it back later in the process before calling the rename function, and it worked fine, sorry for being a bit dented :sweat_smile:

That said, the side-effect of some files “disappearing” from the folder when the rename function is called with a wrong first argument for all files in the folder is still “mysterious” to me and I can still easily reproduce it by changing a . into a _. In a live application the consequences of this weird behavior could be problematic, in particular since Godot itself has an automatic process to convert . into _. If it can help from my testing if the rename function is called with a wrong first argument for less then all the files in the folder it just doesn’t rename but also the files don’t disappear. If all files in the same folder are renamed with a wrong first argument most files in that same folder disappear.

Also the error could be a little bit more verbose than Failed, and the debugger error console is completely silent about it.

Thanks for the support :folded_hands:

1 Like

You should forbid anything other than alphanumeric characters in those filenames. Also mixing node names and file names doesn’t sound like a good idea. Use node’s metadata instead to store the filename string.

1 Like

Right. Godot doesn’t allow . in Node names. It will convert any . into _ and popup and error saying as much. I’ve just tested that and I couldn’t possibly have tought about that being a factor since I’ve never tried using . in Node names, hah!

And you’re absolutely right! If you do this in code:

name = "hello.world"

It will not print an error, and will silently replace the . with _. If there isn’t one, you should probably create a git issue. I’ll do that tomorrow if nobody wants to in the meantime.

1 Like