You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
shutil.move does not work properly with pathlib.Path objects #83321
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2019-12-27.03:13:08.929>created_at=<Date2019-12-26.23:39:08.032>labels= ['type-bug', '3.7']
title='shutil.move does not work properly with pathlib.Path objects'updated_at=<Date2019-12-27.03:13:08.928>user='https://bugs.python.org/LucaPaganin'
Then an AttributeError will be raised, saying that PosixPath objects do not have an rstrip attribute. The error is the following:
Traceback (most recent call last):
File "mover.py", line 10, in <module>
shutil.move(src, dst)
File "/Users/lucapaganin/opt/anaconda3/lib/python3.7/shutil.py", line 562, in move
real_dst = os.path.join(dst, _basename(src))
File "/Users/lucapaganin/opt/anaconda3/lib/python3.7/shutil.py", line 526, in _basenamereturn os.path.basename(path.rstrip(sep))
AttributeError: 'PosixPath' object has no attribute 'rstrip'
Looking into shutil code, line 526, I see that the problem happens when you try to strip the trailing slash using rstrip, which is a method for strings, while PosixPath objects do not have it. Moreover, pathlib.Path objects already manage for trailing slashes, correctly getting basenames even when these are present.
The following two workarounds work:
Explicit cast both src and dst as string using
shutil.move(str(src), str(dst))
This work for both the cases in which dst contains the destination filename or not.
Add the filename to the end of the PosixPath dst object:
dst=pathlib.Path("foodst/bardst/myfile.txt")
Then do
shutil.move(src, dst)
Surely one could use the method pathlib.Path.replace for PosixPath objects, which does the job without problems, even if it requires for dst to contain the destination filename at the end, and lacks generality, since it bugs when one tries to move files between different filesystems.
I think that you should account for the possibility for shutil.move to manage pathlib.Path objects even if one does not provide the destination filename, since the source of the bug is due to a safety measure which is not necessary for pathlib.Path objects, i.e. the managing of the trailing slash.
Do you think that is possible? Thank you in advance.
Luca Paganin
P.S.: I attach a tarball with the dirtree I used for the demonstration.
This is a duplicate of https://bugs.python.org/issue32689 that is fixed in 3.9 . Using os.fspath on path object is more correct here instead of str so that objects with both __str__ and __fspath__ implemented are handled properly.
Activity
LucaPaganin commentedon Dec 26, 2019
Suppose you have two pathlib objects representing source and destination of a move:
If you try to do the following
Then an AttributeError will be raised, saying that PosixPath objects do not have an rstrip attribute. The error is the following:
Looking into shutil code, line 526, I see that the problem happens when you try to strip the trailing slash using rstrip, which is a method for strings, while PosixPath objects do not have it. Moreover, pathlib.Path objects already manage for trailing slashes, correctly getting basenames even when these are present.
The following two workarounds work:
shutil.move(str(src), str(dst))
This work for both the cases in which dst contains the destination filename or not.
Then do
Surely one could use the method pathlib.Path.replace for PosixPath objects, which does the job without problems, even if it requires for dst to contain the destination filename at the end, and lacks generality, since it bugs when one tries to move files between different filesystems.
I think that you should account for the possibility for shutil.move to manage pathlib.Path objects even if one does not provide the destination filename, since the source of the bug is due to a safety measure which is not necessary for pathlib.Path objects, i.e. the managing of the trailing slash.
Do you think that is possible? Thank you in advance.
Luca Paganin
P.S.: I attach a tarball with the dirtree I used for the demonstration.
tirkarthi commentedon Dec 27, 2019
This is a duplicate of https://bugs.python.org/issue32689 that is fixed in 3.9 . Using os.fspath on path object is more correct here instead of str so that objects with both __str__ and __fspath__ implemented are handled properly.