How does the mv command work with external drives? The Next CEO of Stack OverflowHow can the 'mail' command be used?How can I remove the Mac recovery partition from an external drive?How do I write-protect a partition of a USB drive on OSX that can work cross-platform?Fixing my external hard drive's partition mapExternal hard drive : Problems were found with the partition mapIs it possible or likely for malware or a virus to be transferred by plugging a USB hard drive into my Mac?can i use migration assistant to migrate files to a secondary drive?Mounting an external hard disk clone that shares the same partition GUIDs as the source/host hard diskMake Time Machine use two drives from TerminalWhat is the most efficient and reliable method for transfering/copying a large number of files from one external hard drive to another?

Help! I cannot understand this game’s notations!

What connection does MS Office have to Netscape Navigator?

I dug holes for my pergola too wide

Which one is the true statement?

Can I calculate next year's exemptions based on this year's refund/amount owed?

Inexact numbers as keys in Association?

Is there a difference between "Fahrstuhl" and "Aufzug"?

My ex-girlfriend uses my Apple ID to login to her iPad, do I have to give her my Apple ID password to reset it?

Does Germany produce more waste than the US?

Reference request: Grassmannian and Plucker coordinates in type B, C, D

Decide between Polyglossia and Babel for LuaLaTeX in 2019

Easy to read palindrome checker

Aggressive Under-Indexing and no data for missing index

Purpose of level-shifter with same in and out voltages

How to find image of a complex function with given constraints?

How to get the last not-null value in an ordered column of a huge table?

What is the difference between "hamstring tendon" and "common hamstring tendon"?

Physiological effects of huge anime eyes

Can I use the word “Senior” as part of a job title directly in German?

Is a distribution that is normal, but highly skewed, considered Gaussian?

Can I board the first leg of the flight without having final country's visa?

what's the use of '% to gdp' type of variables?

Is French Guiana a (hard) EU border?

Players Circumventing the limitations of Wish



How does the mv command work with external drives?



The Next CEO of Stack OverflowHow can the 'mail' command be used?How can I remove the Mac recovery partition from an external drive?How do I write-protect a partition of a USB drive on OSX that can work cross-platform?Fixing my external hard drive's partition mapExternal hard drive : Problems were found with the partition mapIs it possible or likely for malware or a virus to be transferred by plugging a USB hard drive into my Mac?can i use migration assistant to migrate files to a secondary drive?Mounting an external hard disk clone that shares the same partition GUIDs as the source/host hard diskMake Time Machine use two drives from TerminalWhat is the most efficient and reliable method for transfering/copying a large number of files from one external hard drive to another?










7















On the same drive I assume it would change something like a FAT table to repoint to the location of files.



Question



When going to a different drive (maybe even partition) does the mv command first copy, then remove the old files - in order to prevent data loss if an exception occured ?










share|improve this question

















  • 2





    Note that mv itself doesn't know anything about filesystem internals like the FAT table on a FAT filesystem. As the answers point out, it merely makes a rename() system call, and leaves it to the kernel to return success or failure. The Unix/POSIX file API leaves all the VFS details to the kernel; the kernel itself is the only thing with drivers for HFS+, VFAT, NTFS, etc. See the POSIX rename(2) man page for how simple it is.

    – Peter Cordes
    yesterday















7















On the same drive I assume it would change something like a FAT table to repoint to the location of files.



Question



When going to a different drive (maybe even partition) does the mv command first copy, then remove the old files - in order to prevent data loss if an exception occured ?










share|improve this question

















  • 2





    Note that mv itself doesn't know anything about filesystem internals like the FAT table on a FAT filesystem. As the answers point out, it merely makes a rename() system call, and leaves it to the kernel to return success or failure. The Unix/POSIX file API leaves all the VFS details to the kernel; the kernel itself is the only thing with drivers for HFS+, VFAT, NTFS, etc. See the POSIX rename(2) man page for how simple it is.

    – Peter Cordes
    yesterday













7












7








7


2






On the same drive I assume it would change something like a FAT table to repoint to the location of files.



Question



When going to a different drive (maybe even partition) does the mv command first copy, then remove the old files - in order to prevent data loss if an exception occured ?










share|improve this question














On the same drive I assume it would change something like a FAT table to repoint to the location of files.



Question



When going to a different drive (maybe even partition) does the mv command first copy, then remove the old files - in order to prevent data loss if an exception occured ?







macos command-line external-disk






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 2 days ago









JacksonkrJacksonkr

18218




18218







  • 2





    Note that mv itself doesn't know anything about filesystem internals like the FAT table on a FAT filesystem. As the answers point out, it merely makes a rename() system call, and leaves it to the kernel to return success or failure. The Unix/POSIX file API leaves all the VFS details to the kernel; the kernel itself is the only thing with drivers for HFS+, VFAT, NTFS, etc. See the POSIX rename(2) man page for how simple it is.

    – Peter Cordes
    yesterday












  • 2





    Note that mv itself doesn't know anything about filesystem internals like the FAT table on a FAT filesystem. As the answers point out, it merely makes a rename() system call, and leaves it to the kernel to return success or failure. The Unix/POSIX file API leaves all the VFS details to the kernel; the kernel itself is the only thing with drivers for HFS+, VFAT, NTFS, etc. See the POSIX rename(2) man page for how simple it is.

    – Peter Cordes
    yesterday







2




2





Note that mv itself doesn't know anything about filesystem internals like the FAT table on a FAT filesystem. As the answers point out, it merely makes a rename() system call, and leaves it to the kernel to return success or failure. The Unix/POSIX file API leaves all the VFS details to the kernel; the kernel itself is the only thing with drivers for HFS+, VFAT, NTFS, etc. See the POSIX rename(2) man page for how simple it is.

– Peter Cordes
yesterday





Note that mv itself doesn't know anything about filesystem internals like the FAT table on a FAT filesystem. As the answers point out, it merely makes a rename() system call, and leaves it to the kernel to return success or failure. The Unix/POSIX file API leaves all the VFS details to the kernel; the kernel itself is the only thing with drivers for HFS+, VFAT, NTFS, etc. See the POSIX rename(2) man page for how simple it is.

– Peter Cordes
yesterday










2 Answers
2






active

oldest

votes


















10














macOS's mv is based on the BSD source code. You can find the source code to the mv command online. Using https://github.com/freebsd/freebsd/blob/master/bin/mv/mv.c as a reference, you can see that they do indeed first try to rename the file and then if it is crossing filesystems, it does a cp followed by a rm.



 /*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
}





share|improve this answer




















  • 1





    The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

    – jksoegaard
    2 days ago






  • 2





    @jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

    – ParanoidGeek
    2 days ago






  • 2





    Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

    – jksoegaard
    2 days ago






  • 2





    It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

    – Mike Hill
    2 days ago







  • 2





    Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

    – jksoegaard
    2 days ago


















6














Yes, you're right in thinking that moving a single file on the same file system is really just implemented as a rename operating that the file system structure is changed to update the new name/location of the file, but the file contents are not read/written to the drive again.



When the move happens across two different file systems (drives or partitions), then the mv commands first deletes the destination (if there were an old file there already), copies over the contents of the file to the destination and then finally removes the source file.



The behavior is explained in the manual for mv on macOS:




As the rename(2) call does not work across file systems, mv uses cp(1) and rm(1) to accomplish the move. The effect is equivalent to:



rm -f destination_path && 
cp -pRP source_file destination &&
rm -rf source_file



In regards to the other answer that compares this behavior with the FreeBSD source code - the mv command on macOS is actually a bit different than on FreeBSD. In particular it makes sure that extended attributes and resource forks are moved over correctly and do not disappear when moving across file system boundaries.



You can read the actual macOS source for mv.
You'll see that it is similar in structure as the FreeBSD version, but contains various Apple specific enhancement. In addition to the functionality regarding extended attributes and resource forks as described above, it also has performance enhancements for use with Xsan (distributed file system).



You'll find in the code that first a rename is attempted:





if (!rename(from, to)) 
if (vflg)
printf("%s -> %sn", from, to);
return (0);



If this rename() fails, the code checks why it failed. Especially it checks for the error number EXDEV, which means that the rename would have crossed file systems, and thus cannot be done:



if (errno == EXDEV) 
struct statfs sfs;
char path[PATH_MAX];

/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL)
warnx("cannot resolve %s: %s", from, path);
return (1);

if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname))
warnx("cannot rename a mount point");
return (1);

else
warn("rename %s to %s", from, to);
return (1);



Note here that this code aborts the move in case that the source contains unresolvable symbolic links, or if it is actually a mount point - and also generally if the rename() fails for other reasons than EXDEV.



Only in case that rename() fails with error number EXDEV, and not for the above mentioned reasons, the following code is run:



/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));


This code branches out to do the move between file systems in two different ways depending on whether or not the source to be moved is actually a regular file - or it is something else. "Something else" is usually a directory, a symbolic link, a device node or similar.



In case of a regular file, it uses fastcopy() which simply opens the source and destination files, read()s the data from the source and write()s them to the destination. Unlike the FreeBSD version, the fastcopy() function uses fcopyfile() to copy over ACLs and extended attributes from the source to the destination.



In case of something that is not a regular file, it simply spawns external commands to perform the move: cp for copying and rm for deleting.






share|improve this answer

























  • This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

    – Mike Hill
    2 days ago






  • 1





    Correct! ......

    – jksoegaard
    2 days ago











Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "118"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fapple.stackexchange.com%2fquestions%2f355169%2fhow-does-the-mv-command-work-with-external-drives%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









10














macOS's mv is based on the BSD source code. You can find the source code to the mv command online. Using https://github.com/freebsd/freebsd/blob/master/bin/mv/mv.c as a reference, you can see that they do indeed first try to rename the file and then if it is crossing filesystems, it does a cp followed by a rm.



 /*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
}





share|improve this answer




















  • 1





    The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

    – jksoegaard
    2 days ago






  • 2





    @jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

    – ParanoidGeek
    2 days ago






  • 2





    Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

    – jksoegaard
    2 days ago






  • 2





    It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

    – Mike Hill
    2 days ago







  • 2





    Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

    – jksoegaard
    2 days ago















10














macOS's mv is based on the BSD source code. You can find the source code to the mv command online. Using https://github.com/freebsd/freebsd/blob/master/bin/mv/mv.c as a reference, you can see that they do indeed first try to rename the file and then if it is crossing filesystems, it does a cp followed by a rm.



 /*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
}





share|improve this answer




















  • 1





    The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

    – jksoegaard
    2 days ago






  • 2





    @jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

    – ParanoidGeek
    2 days ago






  • 2





    Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

    – jksoegaard
    2 days ago






  • 2





    It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

    – Mike Hill
    2 days ago







  • 2





    Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

    – jksoegaard
    2 days ago













10












10








10







macOS's mv is based on the BSD source code. You can find the source code to the mv command online. Using https://github.com/freebsd/freebsd/blob/master/bin/mv/mv.c as a reference, you can see that they do indeed first try to rename the file and then if it is crossing filesystems, it does a cp followed by a rm.



 /*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
}





share|improve this answer















macOS's mv is based on the BSD source code. You can find the source code to the mv command online. Using https://github.com/freebsd/freebsd/blob/master/bin/mv/mv.c as a reference, you can see that they do indeed first try to rename the file and then if it is crossing filesystems, it does a cp followed by a rm.



 /*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));
}






share|improve this answer














share|improve this answer



share|improve this answer








edited 2 days ago









user3439894

28.5k64665




28.5k64665










answered 2 days ago









ParanoidGeekParanoidGeek

32115




32115







  • 1





    The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

    – jksoegaard
    2 days ago






  • 2





    @jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

    – ParanoidGeek
    2 days ago






  • 2





    Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

    – jksoegaard
    2 days ago






  • 2





    It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

    – Mike Hill
    2 days ago







  • 2





    Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

    – jksoegaard
    2 days ago












  • 1





    The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

    – jksoegaard
    2 days ago






  • 2





    @jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

    – ParanoidGeek
    2 days ago






  • 2





    Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

    – jksoegaard
    2 days ago






  • 2





    It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

    – Mike Hill
    2 days ago







  • 2





    Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

    – jksoegaard
    2 days ago







1




1





The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

– jksoegaard
2 days ago





The source code snippet you link to actually do not have something to do with the detecting a cross-filesystem move or actually doing a cp followed by a rm. It is only the comment that describes this behavior - the actual code for it is really before the comment. The code after the comment already assumes that it is a cross-device move, and determines whether the source is a regular file to be copied internally, or something else that is moved using calls to the external programs cp and mv.

– jksoegaard
2 days ago




2




2





@jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

– ParanoidGeek
2 days ago





@jksoegaard - Correct. I was highlighting the section of code from the linked source code that directly addressed the question being posed.

– ParanoidGeek
2 days ago




2




2





Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

– jksoegaard
2 days ago





Well, the comment addresses the question. The code does not, as the relevant code is before the comment :-)

– jksoegaard
2 days ago




2




2





It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

– Mike Hill
2 days ago






It looks like the code snippet given is the most relevant part. It is preceeded by if (!rename(from, to)) ... return (0); if (errno == EXDIV) ... else ... return (1); , which, if I'm reading it right, will exit in all scenarios except for those in which the rename fails due to cross-device links. The snippet given shows the methods used to copy in cross-device scenarios: A fast-copy (built into mv) if the source is a regular file, or execution of the cp binary followed by the rm binary otherwise.

– Mike Hill
2 days ago





2




2





Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

– jksoegaard
2 days ago





Yes, I wrote that explanation in my answer above - however the snippet is not alone relevant if you want to look at code. The question was (1) what happens if it is on the same drive (the code before this snippet), and (2) what happens if it is on a different drive (the code after this snippet inside the fastcopy() function for regular files and copy() otherwise). Without knowing what’s inside those functions, the snippet here doesn’t make much sense. You could be led to believe that fastcopy() does a rename(), which it doesn’t.

– jksoegaard
2 days ago













6














Yes, you're right in thinking that moving a single file on the same file system is really just implemented as a rename operating that the file system structure is changed to update the new name/location of the file, but the file contents are not read/written to the drive again.



When the move happens across two different file systems (drives or partitions), then the mv commands first deletes the destination (if there were an old file there already), copies over the contents of the file to the destination and then finally removes the source file.



The behavior is explained in the manual for mv on macOS:




As the rename(2) call does not work across file systems, mv uses cp(1) and rm(1) to accomplish the move. The effect is equivalent to:



rm -f destination_path && 
cp -pRP source_file destination &&
rm -rf source_file



In regards to the other answer that compares this behavior with the FreeBSD source code - the mv command on macOS is actually a bit different than on FreeBSD. In particular it makes sure that extended attributes and resource forks are moved over correctly and do not disappear when moving across file system boundaries.



You can read the actual macOS source for mv.
You'll see that it is similar in structure as the FreeBSD version, but contains various Apple specific enhancement. In addition to the functionality regarding extended attributes and resource forks as described above, it also has performance enhancements for use with Xsan (distributed file system).



You'll find in the code that first a rename is attempted:





if (!rename(from, to)) 
if (vflg)
printf("%s -> %sn", from, to);
return (0);



If this rename() fails, the code checks why it failed. Especially it checks for the error number EXDEV, which means that the rename would have crossed file systems, and thus cannot be done:



if (errno == EXDEV) 
struct statfs sfs;
char path[PATH_MAX];

/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL)
warnx("cannot resolve %s: %s", from, path);
return (1);

if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname))
warnx("cannot rename a mount point");
return (1);

else
warn("rename %s to %s", from, to);
return (1);



Note here that this code aborts the move in case that the source contains unresolvable symbolic links, or if it is actually a mount point - and also generally if the rename() fails for other reasons than EXDEV.



Only in case that rename() fails with error number EXDEV, and not for the above mentioned reasons, the following code is run:



/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));


This code branches out to do the move between file systems in two different ways depending on whether or not the source to be moved is actually a regular file - or it is something else. "Something else" is usually a directory, a symbolic link, a device node or similar.



In case of a regular file, it uses fastcopy() which simply opens the source and destination files, read()s the data from the source and write()s them to the destination. Unlike the FreeBSD version, the fastcopy() function uses fcopyfile() to copy over ACLs and extended attributes from the source to the destination.



In case of something that is not a regular file, it simply spawns external commands to perform the move: cp for copying and rm for deleting.






share|improve this answer

























  • This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

    – Mike Hill
    2 days ago






  • 1





    Correct! ......

    – jksoegaard
    2 days ago















6














Yes, you're right in thinking that moving a single file on the same file system is really just implemented as a rename operating that the file system structure is changed to update the new name/location of the file, but the file contents are not read/written to the drive again.



When the move happens across two different file systems (drives or partitions), then the mv commands first deletes the destination (if there were an old file there already), copies over the contents of the file to the destination and then finally removes the source file.



The behavior is explained in the manual for mv on macOS:




As the rename(2) call does not work across file systems, mv uses cp(1) and rm(1) to accomplish the move. The effect is equivalent to:



rm -f destination_path && 
cp -pRP source_file destination &&
rm -rf source_file



In regards to the other answer that compares this behavior with the FreeBSD source code - the mv command on macOS is actually a bit different than on FreeBSD. In particular it makes sure that extended attributes and resource forks are moved over correctly and do not disappear when moving across file system boundaries.



You can read the actual macOS source for mv.
You'll see that it is similar in structure as the FreeBSD version, but contains various Apple specific enhancement. In addition to the functionality regarding extended attributes and resource forks as described above, it also has performance enhancements for use with Xsan (distributed file system).



You'll find in the code that first a rename is attempted:





if (!rename(from, to)) 
if (vflg)
printf("%s -> %sn", from, to);
return (0);



If this rename() fails, the code checks why it failed. Especially it checks for the error number EXDEV, which means that the rename would have crossed file systems, and thus cannot be done:



if (errno == EXDEV) 
struct statfs sfs;
char path[PATH_MAX];

/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL)
warnx("cannot resolve %s: %s", from, path);
return (1);

if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname))
warnx("cannot rename a mount point");
return (1);

else
warn("rename %s to %s", from, to);
return (1);



Note here that this code aborts the move in case that the source contains unresolvable symbolic links, or if it is actually a mount point - and also generally if the rename() fails for other reasons than EXDEV.



Only in case that rename() fails with error number EXDEV, and not for the above mentioned reasons, the following code is run:



/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));


This code branches out to do the move between file systems in two different ways depending on whether or not the source to be moved is actually a regular file - or it is something else. "Something else" is usually a directory, a symbolic link, a device node or similar.



In case of a regular file, it uses fastcopy() which simply opens the source and destination files, read()s the data from the source and write()s them to the destination. Unlike the FreeBSD version, the fastcopy() function uses fcopyfile() to copy over ACLs and extended attributes from the source to the destination.



In case of something that is not a regular file, it simply spawns external commands to perform the move: cp for copying and rm for deleting.






share|improve this answer

























  • This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

    – Mike Hill
    2 days ago






  • 1





    Correct! ......

    – jksoegaard
    2 days ago













6












6








6







Yes, you're right in thinking that moving a single file on the same file system is really just implemented as a rename operating that the file system structure is changed to update the new name/location of the file, but the file contents are not read/written to the drive again.



When the move happens across two different file systems (drives or partitions), then the mv commands first deletes the destination (if there were an old file there already), copies over the contents of the file to the destination and then finally removes the source file.



The behavior is explained in the manual for mv on macOS:




As the rename(2) call does not work across file systems, mv uses cp(1) and rm(1) to accomplish the move. The effect is equivalent to:



rm -f destination_path && 
cp -pRP source_file destination &&
rm -rf source_file



In regards to the other answer that compares this behavior with the FreeBSD source code - the mv command on macOS is actually a bit different than on FreeBSD. In particular it makes sure that extended attributes and resource forks are moved over correctly and do not disappear when moving across file system boundaries.



You can read the actual macOS source for mv.
You'll see that it is similar in structure as the FreeBSD version, but contains various Apple specific enhancement. In addition to the functionality regarding extended attributes and resource forks as described above, it also has performance enhancements for use with Xsan (distributed file system).



You'll find in the code that first a rename is attempted:





if (!rename(from, to)) 
if (vflg)
printf("%s -> %sn", from, to);
return (0);



If this rename() fails, the code checks why it failed. Especially it checks for the error number EXDEV, which means that the rename would have crossed file systems, and thus cannot be done:



if (errno == EXDEV) 
struct statfs sfs;
char path[PATH_MAX];

/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL)
warnx("cannot resolve %s: %s", from, path);
return (1);

if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname))
warnx("cannot rename a mount point");
return (1);

else
warn("rename %s to %s", from, to);
return (1);



Note here that this code aborts the move in case that the source contains unresolvable symbolic links, or if it is actually a mount point - and also generally if the rename() fails for other reasons than EXDEV.



Only in case that rename() fails with error number EXDEV, and not for the above mentioned reasons, the following code is run:



/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));


This code branches out to do the move between file systems in two different ways depending on whether or not the source to be moved is actually a regular file - or it is something else. "Something else" is usually a directory, a symbolic link, a device node or similar.



In case of a regular file, it uses fastcopy() which simply opens the source and destination files, read()s the data from the source and write()s them to the destination. Unlike the FreeBSD version, the fastcopy() function uses fcopyfile() to copy over ACLs and extended attributes from the source to the destination.



In case of something that is not a regular file, it simply spawns external commands to perform the move: cp for copying and rm for deleting.






share|improve this answer















Yes, you're right in thinking that moving a single file on the same file system is really just implemented as a rename operating that the file system structure is changed to update the new name/location of the file, but the file contents are not read/written to the drive again.



When the move happens across two different file systems (drives or partitions), then the mv commands first deletes the destination (if there were an old file there already), copies over the contents of the file to the destination and then finally removes the source file.



The behavior is explained in the manual for mv on macOS:




As the rename(2) call does not work across file systems, mv uses cp(1) and rm(1) to accomplish the move. The effect is equivalent to:



rm -f destination_path && 
cp -pRP source_file destination &&
rm -rf source_file



In regards to the other answer that compares this behavior with the FreeBSD source code - the mv command on macOS is actually a bit different than on FreeBSD. In particular it makes sure that extended attributes and resource forks are moved over correctly and do not disappear when moving across file system boundaries.



You can read the actual macOS source for mv.
You'll see that it is similar in structure as the FreeBSD version, but contains various Apple specific enhancement. In addition to the functionality regarding extended attributes and resource forks as described above, it also has performance enhancements for use with Xsan (distributed file system).



You'll find in the code that first a rename is attempted:





if (!rename(from, to)) 
if (vflg)
printf("%s -> %sn", from, to);
return (0);



If this rename() fails, the code checks why it failed. Especially it checks for the error number EXDEV, which means that the rename would have crossed file systems, and thus cannot be done:



if (errno == EXDEV) 
struct statfs sfs;
char path[PATH_MAX];

/* Can't mv(1) a mount point. */
if (realpath(from, path) == NULL)
warnx("cannot resolve %s: %s", from, path);
return (1);

if (!statfs(path, &sfs) && !strcmp(path, sfs.f_mntonname))
warnx("cannot rename a mount point");
return (1);

else
warn("rename %s to %s", from, to);
return (1);



Note here that this code aborts the move in case that the source contains unresolvable symbolic links, or if it is actually a mount point - and also generally if the rename() fails for other reasons than EXDEV.



Only in case that rename() fails with error number EXDEV, and not for the above mentioned reasons, the following code is run:



/*
* If rename fails because we're trying to cross devices, and
* it's a regular file, do the copy internally; otherwise, use
* cp and rm.
*/
if (lstat(from, &sb))
warn("%s", from);
return (1);

return (S_ISREG(sb.st_mode) ?
fastcopy(from, to, &sb) : copy(from, to));


This code branches out to do the move between file systems in two different ways depending on whether or not the source to be moved is actually a regular file - or it is something else. "Something else" is usually a directory, a symbolic link, a device node or similar.



In case of a regular file, it uses fastcopy() which simply opens the source and destination files, read()s the data from the source and write()s them to the destination. Unlike the FreeBSD version, the fastcopy() function uses fcopyfile() to copy over ACLs and extended attributes from the source to the destination.



In case of something that is not a regular file, it simply spawns external commands to perform the move: cp for copying and rm for deleting.







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday









Melebius

1617




1617










answered 2 days ago









jksoegaardjksoegaard

19.9k2150




19.9k2150












  • This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

    – Mike Hill
    2 days ago






  • 1





    Correct! ......

    – jksoegaard
    2 days ago

















  • This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

    – Mike Hill
    2 days ago






  • 1





    Correct! ......

    – jksoegaard
    2 days ago
















This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

– Mike Hill
2 days ago





This is a more verbose but much more descriptive answer than the current top-rated answer. From your description, it sounds like the simple answer to OP's question is yes, when working with cross-device moves mv does first copy and then delete the source file.

– Mike Hill
2 days ago




1




1





Correct! ......

– jksoegaard
2 days ago





Correct! ......

– jksoegaard
2 days ago

















draft saved

draft discarded
















































Thanks for contributing an answer to Ask Different!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fapple.stackexchange.com%2fquestions%2f355169%2fhow-does-the-mv-command-work-with-external-drives%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

រឿង រ៉ូមេអូ និង ហ្ស៊ុយលីយេ សង្ខេបរឿង តួអង្គ បញ្ជីណែនាំ

QGIS export composer to PDF scale the map [closed] Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?Print Composer QGIS 2.6, how to export image?QGIS 2.8.1 print composer won't export all OpenCycleMap base layer tilesSave Print/Map QGIS composer view as PNG/PDF using Python (without changing anything in visible layout)?Export QGIS Print Composer PDF with searchable text labelsQGIS Print Composer does not change from landscape to portrait orientation?How can I avoid map size and scale changes in print composer?Fuzzy PDF export in QGIS running on macSierra OSExport the legend into its 100% size using Print ComposerScale-dependent rendering in QGIS PDF output

PDF-ში გადმოწერა სანავიგაციო მენიუproject page