mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
parent
6fe56a329d
commit
6ffface429
4 changed files with 54 additions and 9 deletions
|
@ -191,7 +191,8 @@ Directory and files operations
|
||||||
match one of the glob-style *patterns* provided. See the example below.
|
match one of the glob-style *patterns* provided. See the example below.
|
||||||
|
|
||||||
|
|
||||||
.. function:: copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)
|
.. function:: copytree(src, dst, symlinks=False, ignore=None, \
|
||||||
|
copy_function=copy2, ignore_dangling_symlinks=False)
|
||||||
|
|
||||||
Recursively copy an entire directory tree rooted at *src*, returning the
|
Recursively copy an entire directory tree rooted at *src*, returning the
|
||||||
destination directory. The destination
|
destination directory. The destination
|
||||||
|
@ -282,7 +283,7 @@ Directory and files operations
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. function:: move(src, dst)
|
.. function:: move(src, dst, copy_function=copy2)
|
||||||
|
|
||||||
Recursively move a file or directory (*src*) to another location (*dst*)
|
Recursively move a file or directory (*src*) to another location (*dst*)
|
||||||
and return the destination.
|
and return the destination.
|
||||||
|
@ -295,15 +296,26 @@ Directory and files operations
|
||||||
:func:`os.rename` semantics.
|
:func:`os.rename` semantics.
|
||||||
|
|
||||||
If the destination is on the current filesystem, then :func:`os.rename` is
|
If the destination is on the current filesystem, then :func:`os.rename` is
|
||||||
used. Otherwise, *src* is copied (using :func:`shutil.copy2`) to *dst* and
|
used. Otherwise, *src* is copied to *dst* using *copy_function* and then
|
||||||
then removed. In case of symlinks, a new symlink pointing to the target of
|
removed. In case of symlinks, a new symlink pointing to the target of *src*
|
||||||
*src* will be created in or as *dst* and *src* will be removed.
|
will be created in or as *dst* and *src* will be removed.
|
||||||
|
|
||||||
|
If *copy_function* is given, it must be a callable that takes two arguments
|
||||||
|
*src* and *dst*, and will be used to copy *src* to *dest* if
|
||||||
|
:func:`os.rename` cannot be used. If the source is a directory,
|
||||||
|
:func:`copytree` is called, passing it the :func:`copy_function`. The
|
||||||
|
default *copy_function* is :func:`copy2`. Using :func:`copy` as the
|
||||||
|
*copy_function* allows the move to succeed when it is not possible to also
|
||||||
|
copy the metadata, at the expense of not copying any of the metadata.
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
Added explicit symlink handling for foreign filesystems, thus adapting
|
Added explicit symlink handling for foreign filesystems, thus adapting
|
||||||
it to the behavior of GNU's :program:`mv`.
|
it to the behavior of GNU's :program:`mv`.
|
||||||
Now returns *dst*.
|
Now returns *dst*.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Added the *copy_function* keyword argument.
|
||||||
|
|
||||||
.. function:: disk_usage(path)
|
.. function:: disk_usage(path)
|
||||||
|
|
||||||
Return disk usage statistics about the given path as a :term:`named tuple`
|
Return disk usage statistics about the given path as a :term:`named tuple`
|
||||||
|
|
|
@ -176,6 +176,14 @@ ipaddress
|
||||||
network objects from existing addresses (contributed by Peter Moody
|
network objects from existing addresses (contributed by Peter Moody
|
||||||
and Antoine Pitrou in :issue:`16531`).
|
and Antoine Pitrou in :issue:`16531`).
|
||||||
|
|
||||||
|
shutil
|
||||||
|
------
|
||||||
|
|
||||||
|
* :func:`~shutil.move` now accepts a *copy_function* argument, allowing,
|
||||||
|
for example, :func:`~shutil.copy` to be used instead of the default
|
||||||
|
:func:`~shutil.copy2` if there is a need to ignore metadata. (Contributed by
|
||||||
|
Claudiu Popa in :issue:`19840`.)
|
||||||
|
|
||||||
signal
|
signal
|
||||||
------
|
------
|
||||||
|
|
||||||
|
|
|
@ -486,7 +486,7 @@ def _basename(path):
|
||||||
sep = os.path.sep + (os.path.altsep or '')
|
sep = os.path.sep + (os.path.altsep or '')
|
||||||
return os.path.basename(path.rstrip(sep))
|
return os.path.basename(path.rstrip(sep))
|
||||||
|
|
||||||
def move(src, dst):
|
def move(src, dst, copy_function=copy2):
|
||||||
"""Recursively move a file or directory to another location. This is
|
"""Recursively move a file or directory to another location. This is
|
||||||
similar to the Unix "mv" command. Return the file or directory's
|
similar to the Unix "mv" command. Return the file or directory's
|
||||||
destination.
|
destination.
|
||||||
|
@ -503,6 +503,11 @@ def move(src, dst):
|
||||||
recreated under the new name if os.rename() fails because of cross
|
recreated under the new name if os.rename() fails because of cross
|
||||||
filesystem renames.
|
filesystem renames.
|
||||||
|
|
||||||
|
The optional `copy_function` argument is a callable that will be used
|
||||||
|
to copy the source or it will be delegated to `copytree`.
|
||||||
|
By default, copy2() is used, but any function that supports the same
|
||||||
|
signature (like copy()) can be used.
|
||||||
|
|
||||||
A lot more could be done here... A look at a mv.c shows a lot of
|
A lot more could be done here... A look at a mv.c shows a lot of
|
||||||
the issues this implementation glosses over.
|
the issues this implementation glosses over.
|
||||||
|
|
||||||
|
@ -527,11 +532,13 @@ def move(src, dst):
|
||||||
os.unlink(src)
|
os.unlink(src)
|
||||||
elif os.path.isdir(src):
|
elif os.path.isdir(src):
|
||||||
if _destinsrc(src, dst):
|
if _destinsrc(src, dst):
|
||||||
raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
|
raise Error("Cannot move a directory '%s' into itself"
|
||||||
copytree(src, real_dst, symlinks=True)
|
" '%s'." % (src, dst))
|
||||||
|
copytree(src, real_dst, copy_function=copy_function,
|
||||||
|
symlinks=True)
|
||||||
rmtree(src)
|
rmtree(src)
|
||||||
else:
|
else:
|
||||||
copy2(src, real_dst)
|
copy_function(src, real_dst)
|
||||||
os.unlink(src)
|
os.unlink(src)
|
||||||
return real_dst
|
return real_dst
|
||||||
|
|
||||||
|
|
|
@ -1592,6 +1592,24 @@ class TestMove(unittest.TestCase):
|
||||||
rv = shutil.move(self.src_file, os.path.join(self.dst_dir, 'bar'))
|
rv = shutil.move(self.src_file, os.path.join(self.dst_dir, 'bar'))
|
||||||
self.assertEqual(rv, os.path.join(self.dst_dir, 'bar'))
|
self.assertEqual(rv, os.path.join(self.dst_dir, 'bar'))
|
||||||
|
|
||||||
|
@mock_rename
|
||||||
|
def test_move_file_special_function(self):
|
||||||
|
moved = []
|
||||||
|
def _copy(src, dst):
|
||||||
|
moved.append((src, dst))
|
||||||
|
shutil.move(self.src_file, self.dst_dir, copy_function=_copy)
|
||||||
|
self.assertEqual(len(moved), 1)
|
||||||
|
|
||||||
|
@mock_rename
|
||||||
|
def test_move_dir_special_function(self):
|
||||||
|
moved = []
|
||||||
|
def _copy(src, dst):
|
||||||
|
moved.append((src, dst))
|
||||||
|
support.create_empty_file(os.path.join(self.src_dir, 'child'))
|
||||||
|
support.create_empty_file(os.path.join(self.src_dir, 'child1'))
|
||||||
|
shutil.move(self.src_dir, self.dst_dir, copy_function=_copy)
|
||||||
|
self.assertEqual(len(moved), 3)
|
||||||
|
|
||||||
|
|
||||||
class TestCopyFile(unittest.TestCase):
|
class TestCopyFile(unittest.TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue