Fail to rename a file with different case in Mac
gnoeyp opened this issue · 6 comments
Path:rename() does not allow to rename "abc.txt" to "Abc.txt"
The mac filesystem is case insensitive so a rename of abc.txt
to Abc.txt
is nonsensical (to the OS) as they are the same.
abc.txt
and Abc.txt
can't exist in the same directory, but it is still possible to rename abc.txt
to Abc.txt
using Finder or terminal, if there is no duplication. I often need to rename a file in camel case to pascal case, or conversely. Is it not possible to add this feature?
I don't know the work effort to do this, it would depend on if luv
(the underlying lua tool that is used to interface with the host) supports this. This will have to wait for someone more intimately familiar with that section of the codebase. Can you share the error you are receiving when you attempt the rename? And can you verify that you can execute an mv abc.txt Abc.txt
?
The mac filesystem is case insensitive so a rename of
abc.txt
toAbc.txt
is nonsensical (to the OS) as they are the same.
File name comparisons are done without regard to case, however, the fs is also case-preserving, meaning that file names are stored and retrieved exactly how they were entered. This is generally the case for most modern/common "case-insensitive" filesystems I believe (unless you are on something like DOS, which is not a modern OS).
Just because the current host/fs has a case-insensitive fs doesn't mean that that will always be the case for a given repo/codebase. For example, if you were working on a shared codebase on macOS, it may become necessary at some point (hypothetically speaking) to rename a makefile
to Makefile
(as the former wouldn't work on case-sensitive file systems, even though it would on your own), etc. So there definitely seems to be a use-case for wanting to do such a thing, even on a case-insensitive fs.
The error is being thrown by Plenary itself in Path:rename()
.
I don't think the fix is trivial, nor could it be perfect and unsusceptible to edge-case race conditions, but I may give it a shot and send in a patch/pr 😄. I'm not super familiar with Plenary's code though, although it does seem that Path:rename()
is missing type annotations and might have some unnecessary code in its impl. The reason the fix is probably not easy/simple is because:
- the current behavior of
Path:rename()
is to not allow clobbering/overwriting the new filename if it appears to already exist (and this differs from the semantics of therename(2)
syscall alone, which is the function thatPath:rename()
is ultimately using/wrapping to do the rename), and furthermore there is no option/arg that one could pass to "force" it - I could be wrong, but there doesn't appear to be a trivial/universal/solid/builtin/canonical way to check for case-sensitivity (e.g. even mac/darwin can have case-sensitive filesystems,
statfs()
doesn't appear to give you that kind of info, etc.).
Therefore, the solution will probably end up being something rather manual and "hacky", if the current behavior as described in 1.
is to be retained.
I think I may have almost reached a solution.
On an unrelated note, I also came across 2 or 3 small bugs in Path:rename()
as well (that have to do with using stat instead of lstat, or extracting the wrong substring causing a newpath such as ./*
to throw). I'll try to fix those too.