Reputation: 1422
I'm under Win10/x64 using cygwin64 bash.
I have a problem copying a simple directory (../bin below) which only contains 2 files, a Win10 executable and the corresponding executable for Linux (same file name with no extension).
$ ls ../bin
abc abc.exe*
$ cp -rf ../bin .
cp: cannot create regular file './bin/abc': File exists
$ ls bin
abc.exe*
Why the file abc is not copied !?
If I rename abc.exe to abcd.exe in ../bin, then it works and the 2 files are copied.
How to tell bash/cp to not consider abc and abc.exe as the same file ? I tried various cp options (-f, -p, -H) it does not solve the problem.
Thanks.
Upvotes: 2
Views: 943
Reputation: 3041
This issue is to do with the special way in which Cygwin handles .exe
files. If you have a file in your current directory say, test.exe
, Cygwin has always allowed it to be executed by running ./test
without the .exe
extension.
It does this inside its implementation of certain system calls which take a file name by checking if a file with the same name, but with the .exe
extension exists, then operating on that instead. From a post on the Cygwin mailing list:
Cygwin always handled the .exe suffix transparently in terms of stat(2) calls, but Cygwin 1.7 also handles them transparently in terms of open(2) and any other call. Therefore, if a file foo.exe exists, and an application calls stat("foo"), it will get told that, yes, "foo" exists. That's a basic component of being able to call foo.exe from bash by just typing foo. POSIX systems just don't have the .exe suffix for executables.
However, this creates an issue where if a file already exists with the .exe
extension, problems will arise if you try to create a file of the same name in the same directory without an extension.
Seemingly (as per the mailing list post), this usually occurs when extracting a tar file. In the case of the OP, it occurred when using the cp -r
command to copy from a different directory where the files were created by a Windows IDE.
The workaround is to always create the file without the extension first, the create the .exe
file. For this, instead of using cp -r
it is possible to use the pax
utility to copy non .exe
files first. From within the source directory, do:
find . \! -name '*.exe' -print0 | pax -0drw dest_dir
find . -name '*.exe' -print0 | pax -0drw dest_dir
Note that the Cygwin find
command does not support using +
with -exec
(which otherwise would be used for the preferred way to do this). Alternatively GNU cpio
can be used:
find . \! -name '*.exe' -print0 | cpio -p --null dest_dir
find . -name '*.exe' -print0 | cpio -p --null dest_dir
Upvotes: 3