Bug 508514 - moving files to trash across filesystems is slow
Summary: moving files to trash across filesystems is slow
Status: REPORTED
Alias: None
Product: dolphin
Classification: Applications
Component: general (other bugs)
Version First Reported In: 25.04.2
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Dolphin Bug Assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-08-20 11:42 UTC by Milan Hauth
Modified: 2025-08-20 19:31 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Milan Hauth 2025-08-20 11:42:47 UTC
SUMMARY
removing files from an external hard drive is slow
because the files are moved to the filesystem of ~/.local/share/Trash/files/

STEPS TO REPRODUCE
1. remove a large file on a filesystem different from ~/.local/share/Trash/files/

OBSERVED RESULT
files are moved across different filesystems, which is slow

EXPECTED RESULT
it should try to move files to /.local/share/Trash/files/ on the same filesytem
and only if that fails, it should move files to ~/.local/share/Trash/files/

python script:
https://github.com/milahu/random/blob/master/python/trash-on-same-filesystem.py

~~~
#!/usr/bin/env python3
# move files to trash, the "smart" way. "smart" as in:
# try to avoid moving files across different filesystems (which is slow)
# FIXME mp_trash_path is readable by other users
import os, sys
trash_subpath = ".local/share/Trash/files"
default_trash_path = os.path.realpath(os.path.join(os.environ["HOME"], trash_subpath))
# default_trash_dev = os.stat(default_trash_path).st_dev; print("default_trash_dev", default_trash_dev)
def find_mount_point(path): # https://stackoverflow.com/a/4453715/10440128
    path = os.path.realpath(path)
    while not os.path.ismount(path):
        path = os.path.dirname(path)
    return path
def get_path2(path, trash_dir):
    os.makedirs(trash_dir, exist_ok=True)
    path2 = os.path.join(trash_dir, os.path.basename(path))
    return path2
for path in sys.argv[1:]:
    print("trashing", repr(path))
    # path_dev = os.stat(path).st_dev; print("path_dev", path_dev)
    mp_path = find_mount_point(path)
    print("  mp_path", repr(mp_path))
    mp_trash_path = os.path.realpath(os.path.join(mp_path, trash_subpath))
    done_move = False
    for trash_path in set([default_trash_path, mp_trash_path]):
        path2 = get_path2(path, trash_path)
        try:
            os.rename(path, path2) # this only works on the same filesystem
            print(f"  fast path: moved file to the same-filesystem trash {trash_path}")
            done_move = True
            break
        except OSError as exc: # [Errno 18] Invalid cross-device link
            pass # path and path2 are on different filesystems
    if done_move: continue
    trash_path = default_trash_path
    path2 = get_path2(path, trash_path)
    shutil.move(path, path2) # slow path: copy + unlink
    print(f"  slow path: moved file to the other-filesystem trash {trash_path}")
~~~

SOFTWARE/OS VERSIONS
OS: NixOS Linux
KDE Plasma Version: 6.4.0
KDE Frameworks Version: 6.15.0
Qt Version: 6.9.0

ADDITIONAL INFORMATION
this may be a qt bug in QFile::moveToTrash
https://doc.qt.io/qt-6/qfile.html#moveToTrash
Comment 1 Milan Hauth 2025-08-20 11:55:32 UTC
similar issue in gnu-coreutils when moving files across bind mounts
https://github.com/milahu/move-files-across-bind-mounts