Recursively move a file or directory to another location. This is similar to the Unix "mv" command. Return the file or directory's destination. If dst is an existing directory or a symlink to a directory, then src is moved inside that directory. The destination path in that director
(src, dst, copy_function=copy2)
| 874 | return os.path.basename(path.rstrip(sep)) |
| 875 | |
| 876 | def move(src, dst, copy_function=copy2): |
| 877 | """Recursively move a file or directory to another location. This is |
| 878 | similar to the Unix "mv" command. Return the file or directory's |
| 879 | destination. |
| 880 | |
| 881 | If dst is an existing directory or a symlink to a directory, then src is |
| 882 | moved inside that directory. The destination path in that directory must |
| 883 | not already exist. |
| 884 | |
| 885 | If dst already exists but is not a directory, it may be overwritten |
| 886 | depending on os.rename() semantics. |
| 887 | |
| 888 | If the destination is on our current filesystem, then rename() is used. |
| 889 | Otherwise, src is copied to the destination and then removed. Symlinks are |
| 890 | recreated under the new name if os.rename() fails because of cross |
| 891 | filesystem renames. |
| 892 | |
| 893 | The optional `copy_function` argument is a callable that will be used |
| 894 | to copy the source or it will be delegated to `copytree`. |
| 895 | By default, copy2() is used, but any function that supports the same |
| 896 | signature (like copy()) can be used. |
| 897 | |
| 898 | A lot more could be done here... A look at a mv.c shows a lot of |
| 899 | the issues this implementation glosses over. |
| 900 | |
| 901 | """ |
| 902 | sys.audit("shutil.move", src, dst) |
| 903 | real_dst = dst |
| 904 | if os.path.isdir(dst): |
| 905 | if _samefile(src, dst) and not os.path.islink(src): |
| 906 | # We might be on a case insensitive filesystem, |
| 907 | # perform the rename anyway. |
| 908 | os.rename(src, dst) |
| 909 | return |
| 910 | |
| 911 | # Using _basename instead of os.path.basename is important, as we must |
| 912 | # ignore any trailing slash to avoid the basename returning '' |
| 913 | real_dst = os.path.join(dst, _basename(src)) |
| 914 | |
| 915 | if os.path.exists(real_dst): |
| 916 | raise Error("Destination path '%s' already exists" % real_dst) |
| 917 | try: |
| 918 | os.rename(src, real_dst) |
| 919 | except OSError: |
| 920 | if os.path.islink(src): |
| 921 | linkto = os.readlink(src) |
| 922 | os.symlink(linkto, real_dst) |
| 923 | os.unlink(src) |
| 924 | elif os.path.isdir(src): |
| 925 | if _destinsrc(src, dst): |
| 926 | raise Error("Cannot move a directory '%s' into itself" |
| 927 | " '%s'." % (src, dst)) |
| 928 | if (_is_immutable(src) |
| 929 | or (not os.access(src, os.W_OK) and os.listdir(src) |
| 930 | and sys.platform == 'darwin')): |
| 931 | raise PermissionError("Cannot move the non-empty directory " |
| 932 | "'%s': Lacking write permission to '%s'." |
| 933 | % (src, src)) |
nothing calls this directly
no test coverage detected
searching dependent graphs…