how to determine if files are on same or different file systems

Peter Otten __peter__ at web.de
Sun Dec 7 08:05:20 EST 2003


Kamus of Kadizhar wrote:

> Peter Otten wrote:
> 
>> No need to determine it beforehand, just try (untested):
>> 
>> def movefile(src, dst):
>>     try:
>>         os.rename(src, dst)
>>     except OSError:
>>         shutil.copy2(src, dst)
>>         os.remove(src)
>> 
>> 
>> Of course, if you are using Python 2.3 you should use shutil.move() as
>> pointed out by Serge Orlov; the above was mostly posted to illustrate the
>> popular concept "It's easier to ask forgiveness than permission", i. e.
>> with Python's powerful exception handling mechanism you need not fear the
>> failure of a particular code snippet, as long as you provide the
>> appropriate error handling.
> 
> Peter:
> 
> I am copying 600mb - 1.2gb files over slow wireless to an NFS mount -
> not exactly the model of reliability.  It takes 40 minutes to an hour to
> copy one of these.  I am paranoid of failures - I don't want to lose
> movies.
> 
> So, I don't want to rely on innate error handling, because the failure
> could come from wireless failure, and the copy could fail as well.
> That's why I'm looking for a way to tell if a particular partition is
> network mounted.
> 
> The basic idea is that movies get moved on the same partition, but
> copied (and not deleted) when moving between network mounted partitions
> and local partitions.  Deletes will be subject to manual review until I
> get a comfort factor.
> 

I still think that EAFP

try:
    os.rename(src, dst)
except OSError:
    # any error here will still result in a traceback 
    # if not handled in client code
    shutil.copy2(src, dst) 
    # os.remove() ommitted intentionally

is superior style to LBYL (look before you leap)

if isSamePartition(src, dst):
    os.rename(src, dst)
else:
    shutil.copy2(src, dst)

and fail to see the increased danger for your data. Plus, it saves you from
writing the nonexistent isSamePartition() :-)
Maybe you could replace the copy2() call with the invocation of some utility
that reliably copies over an unreliable connection (maybe can someone else
come up with a name), or you take the extra amount of work/time and compare
the two files after you have copied them.

>> 
>> Random remarks:
>> - You might take a look at os.path.join()
>> - Ok, this is paranoia, but I would ensure that ".avi" is only at the end
>> of the string
> 
> ".avi$" ? I still haven't figured out Python's string handling really
> well.  Or use the length of the string and count backwards?  I admit, I
> got lazy on this one.

Use regular expressions only as a last resort.

>>> import os
>>> path = "/dir/name.ext"
>>> os.path.splitext(path)
('/dir/name', '.ext')

Putting it into a function:

>>> def changeext(path, newext=""):
...     return os.path.splitext(path)[0] + newext
...
>>> changeext("/sowhat/movie.mpg", ".jpg")
'/sowhat/movie.jpg'
>>> changeext("/sowhat/movie.mpg")
'/sowhat/movie'
>>> changeext("/sowhat/movie", ".jpg")
'/sowhat/movie.jpg'

I you want to do it only with string methods:

>>> path = "/one/two.three"
>>> path[:path.rindex(".")] + ".four"
'/one/two.four'

However, you would have to ensure that the dot position is after the last
slash.

For a quick overview what is available for strings:

>>> dir(str)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__',
'__ge__', '__getattribute__', '__getitem__', '__getnewargs__',
'__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__',
'__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__',
'__str__', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith',
'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower',
'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip',
'replace', 'rfind', 'rindex', 'rjust', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

Peter






More information about the Python-list mailing list