Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting if File.Move will require 'Copy -> Delete' or just alter location in the file system table

Disclaimer: I will admit straight away I have a fair amount of ignorance regarding the details on how file systems function. I have been using NTFS for so long that I can extrapolate what is going on based on behaviors I have witnessed, as well as whatever I have learned from dorking on the internet - however...

I was hoping that there is a way to detect if when moving a file from 'location A' to 'location B', whether the operation will require the equivalent of 'File.Copy -> File.Delete' or if it will not copy the actual file data, but just update the location in the 'master file table' or the like.

For various purposes, I sometimes move large numbers of large files. I like to report progress in the UI.

I realize that when I call File.Move and move a file from a location on one disk/partition to another, that the function will effectively have to 'copy file data -> delete' between the disks / partitions. When it encounters this situation, I want to be able to detect that this will happen so I can use code I have authored that will copy the file and give detailed progress reporting as bytes are transferred so I can update progress bars in the UI frequently.

When it is on the same disk/partition, as updating the location in the master file table is so fast, I simply update the progress bar when the file.Move function completes for each file I am batch moving.

Using .NET 4 (C#), is it possible to detect through other means whether calling the File.Move will require an equivalent 'copy -> delete' operation or will simply update a file table and not copy the file data?

Edit:

As I note in comments below, possibilities on how I thought this might be done would be to detect if a given source file location and destination file location are located on the same physical disk & partition, and if so, would this mean I could accurately anticipate the behavior and decide what functions to call - the built in File.Move function for the 'near instant' update file system table that I believe occurs when moving to same disk/part, or my more detailed 'report progress every 'x' bytes copied' custom file copy code. File transfer speeds can vary greatly on the machines my programs will run on so I like to be able to report detailed progress / present transfer speed when possible.

Note - The program may be using network UNC paths which can be using different physical disks with the same root path i.e.: \\somename\shares\workfolder\project may be on a different physical disk then \\somename\shares\workfoldder\otherproject. So I would need a method for detecting the partition ID or physical disk ID to see if a source and destination folder on on the same disk/partition.

Thank you

like image 920
JHubbard80 Avatar asked Sep 08 '11 06:09

JHubbard80


3 Answers

You could always P/Invoke to MoveFileWithProgress. From a cursory reading, it looks like it'll give you more granular progress when a file is copied, rather than moved.

Alternatively, there's always SHFileOperation, which'll give you the Windows Explorer UI and semantics.

like image 65
Roger Lipscombe Avatar answered Oct 13 '22 13:10

Roger Lipscombe


I don't think you can detect such a thing in a normal way as you're not supposed to care. If you could test this, what would be the if and else case be as no knowledge can be extracted from this (except for the speed of the transfer).

In .net the file system is abstracted so you can just move files from one place to another without knowing what partition/filesystem/network drive you're copying from/to.

For your specific problem, why don't you always show the progressbar and have it updated at a certain interval for both cases.

like image 20
thekip Avatar answered Oct 13 '22 13:10

thekip


I'm pretty sure that you can't do this.

For starters even on NTFS just looking at the drive letter for local drives isn't enough because you can mount a drive inside an empty folder on an existing drive. This means that even if the two paths have the same drive letter they could still be mounted on different disks.

To take it another step further consider external shares, possibly ones mounted on an *nix based system and exposed via Samba. *nix symbolic links make it impossible to tell whether two paths reside on the same physical device by looking at paths alone - the only option have would be to query the remote machine "do these two paths exist on the same drive?", something which I very much doubt would be exposed.

I would just use File.Move and accept that you don't get progress updates. Writing your own copy implementation strikes me as a "not a particularly good idea" anyway.

like image 28
Justin Avatar answered Oct 13 '22 15:10

Justin