With great power comes great responsibility
– some guy
I recently got myself into big trouble using the force keyword. the documentation is clear, it will delete the destination. My misunderstanding was that the destination would be my source file name, i.e. it would overwrite the file if i was trying to copy over a previous version - i made the mistake of assuming it worked like unix cp, i.e. force meant it would simply overwrite the target with the same name to make updating a file with a new copy easier.
but the documentation is clear, it will DELETE THE DESTINATION. my destination was a directory full of data, and i was trying to copy a file to it. sure, i did a very dumb thing, and sure it’s convenient, but it’s a trap.
How about :
1 removing it - force the user to remove the file/directory explicitly. slightly more inconvenient but would force the user to apply a little extra thought to the process.
2 makes it’s operation more unix cp like, i.e. it will only remove something that has the same name as the source, i.e. cp(“somefile.txt”, “somedir”, force=true) will overwrite somefile.txt but won’t delete somedir.
yes, all my fault. yes it’s convenient, but I can hardly believe i’m the first person to have fallen into this trap.
just as reference neither python’s shutil copy or copyfile allow such a thing.
The purpose of the
force argument in
cp & friends is precisely that it allows to skip checking existing files — it will succeed if you have write permissions and the disk is not full.
Failing for directories would defeat the purpose. As would imitating Unix’s
cp: if I did
cp(src, dest; force = true)
and it does not error, I can reasonably expect that
dest now has the contents I intended. Your suggestion would silently place it at
A major difference between the
cp of most shells and Julias
cp function is that in a shell
cp file dir
will copy the file “file” into the directory “dir” (if “dir” exists and is a directory.)
In Julia, on the other hand
will throw an
ArgumentError if there’s a directory named “dir”.
Maybe one could introduce a new kwarg and change that error to: “ArgumentError: ‘dir’ exists and is a directory. Use
into=true to copy ‘file’ into ‘dir’, or use
force=true to remove ‘dir’ before copying.”
i’ve been thinking about this, wondering why nobody else thinks that a flag set to true causing the deletion of an entire directory is not a problem.
but instead of complaining some more, here’s my suggestion:
copyfile(src, dest, force::Boolean)
the semantics are obvious ( i think), but i’ll spell it out anyway
src must be a filename.
dest can be a directory or a filename
if dest is a directory, the file is copied to the directory.
if dest is a filename, the file is copied to the new filename.
so the actual destination filename is either dest or src/dest
force=true causes the destination FILE to be deleted if it exists.
force=false throws an error if the destination FILE exists.
in fact, an update flag might be a nice-to-have also, so that the destination file isn’t overwritten unless src is newer.
I’m going to write it up for my own use. happy to contribute it to the filesystem module