App for deleting obsolete files under /home/username

Hallo!

When you use a KDE-App (the same with other DEs), a lot or files have been created or modified under ~/home/username/.
In opposite, when you uninstall it, theese files, remein there until you delete them manually.
Over the years the system can accumulate hundred of them, also related to obsolete or no more existing applications.

MY QUESTION:
There is maybe a tool or a script that makes this work?

Under KDE-Anwendungen I did not find any.
Sweeper only clean unwanted system traces, like cookies, history …
BleachBit does almost the same.

Thank a lot for suggestion

I have a Fish Function for Arch Linux that achieves this either while uninstalling, or even after you’ve uninstalled. It should be able to work on any distro with a slight modification. See below.

The Arch Script (it’s hosted on my Codeberg), but you can just copy it here and modify it based on your distro:

function rnsu
    if test (count $argv) -eq 0
        echo "Usage: rnsu package_name"
        return 1
    end

    set package_name $argv[1]

    # Run the pacman command
    sudo pacman -Rnsu $package_name

    # Ask the user if they want to remove the related files
    read -P "Would you like to remove the related configs for \"$package_name\"? (y/n): " response

    if test "$response" = "y"
        set directories /home ~/.config ~/.cache ~/.local/share
        set found_items 0

        # First pass: display what would be deleted
        for dir in $directories
            set -l matches (find $dir -maxdepth 2 -iname "*$package_name*" 2>/dev/null)
            if test (count $matches) -gt 0
                set found_items 1
                for match in $matches
                    echo "Found: $match"
                end
            end
        end

        if test $found_items -eq 1
            # Second pass: collect all matches for individual deletion
            set all_matches
            for dir in $directories
                set matches (find $dir -maxdepth 2 -iname "*$package_name*" 2>/dev/null)
                if test (count $matches) -gt 0
                    set -a all_matches $matches
                end
            end

            set deleted_count 0
            for match in $all_matches
                read -P "Delete '$match'? (y/n): " response
                if test "$response" = "y"
                    echo "Moving to trash: $match"
                    trash -v $match
                    set deleted_count (math $deleted_count + 1)
                end
            end

            if test $deleted_count -gt 0
                echo "Moved $deleted_count item(s) to trash."
            else
                echo "No items were deleted."
            end
        else
            echo "No related files or folders found for \"$package_name\"."
        end
    else
        echo "No files or directories have been removed or sent to the trash."
    end
    # Orphan warning message
    echo "Tip: Check for orphans using pacman's -Qdtq argument to find no longer required packages."
    echo "You can re-run \"rnsu\" with these packages individually, but you probably don't need to."
end

For Debian/Ubuntu-based, you’d just need to change a few lines:

# Change these two lines

# Run the pacman command
sudo pacman -Rnsu $package_name

to

# Run the apt command
sudo apt remove $package_name

# And change this line

"Tip: Check for orphans using pacman's -Qdtq argument to find no longer required packages."

to

"Tip: Check for orphans using apt's autoremove argument to find no longer required packages."



A Few Notes:

  • Make sure you have trash-cli installed.
  • The files/directories are only sent to the trash, which gives you the opportunity to undo in case you make a mistake.

Lastly, if you use it while uninstalling, it may not work on some packages, since the name of the package and the name the app uses for its directories may be different.

The example above illustrates this. I am currently on MX Linux, and the actual package name is “ephoto-bl”. So, all you have to do after you uninstall is run “rnsu ephoto” - without the “-bl” - and this will get the directory as intended.

Oh, and to confirm, this works with any package, not just KDE packages.
More specifically, it searches home, .config, .cache, and .local/share.

you can use kfind to search for files that haven’t been modified in a while and see if their folders remind you of any old software that has since been deleted…

i don’t know of any apps that automate this for you… that would seem like a dangerous proposal.

That ist the methode, I’m using. But … You know: too much time to spend with it

Thanks a lot for suggestion.!

@ddnnacheta
Thanks a lot for suggestion.!

Now I have to:

  • install the fish console, It probably offers some functions, which are not in KDE-Konsole. → very simple
  • install trash-cli. Not in standard repos of OpenSUSE, but alrady found.
  • understand the commands and the command options, you have wrote in the script and find the corrispondent ones in zypper (the package manager under OpenSUSE).
    This operations are for me almost cryptos! I 'll maybe ask for help in the OpenSUSE Forum.

A addendly question:
could the script works with word patterns?. I.e.:

set package:name $sane*
sudo pacman -Rnsu $package_name

Fish will work in Konsole just fine - in any terminal, really.
It’s just a shell, not a full-blown independent console.

For openSUSE, the remove command would be sudo zypper rm $package_name.

You’d need to do it like this since Fish works a little differently than Bash, and Zypper interprets * differently as well:

set package_name "sane*"
sudo zypper rm $package_name

I’m not running openSUSE right now to test it, but this should work.

Yes, it does!
Many thanks !!!
However there are oft more /home subdirectories to consider. Should I add them in the fish script or there is a command, tha make the search recursive?

Usually, /home is only for Firefox (and its forks), Thunderbird, and a few other applications that store their configs there. Most applications use .config, .cache, and local/share. But, if you would like it to search deeper, change the max depth value from 2 to a higher number like 4, or something else.

Search for: maxdepth 2 then change it to something more desired.

maxdepth 4

But, since /home is included in the list already, it would be going into every base directory in /home down to 4 levels deep. I’s not actually an issue, but just make sure to read which files/directories it finds for deletion and decide which ones to remove.

Again, if you make a mistake, the file/directory isn’t gone until you empty the trash.

The original poster desires an automated tool to clean files in /home/username/. But why?

Having mental bliss of knowing that folder is cleaned up is a decent reason. But what is considered cleaned up? Does low storage usage suffice as clean? Does the lack of sensitive data suffice?

There might be reason that on Windows a bunch of directories also get cluttered with dozens of accumulated files that are no longer used:

  • When you reinstall the program, some user data or plugins may be restored
  • It doesn’t take up too much space, so might as well keep it.

But there are reasonable objections, because sometimes it contains sensitive data, or it uses big files that take up space. Then my advice is threefold (descending effort) :

  • Suggest KDE to make a native app or function in system setting to automatically clean unused files in home folder. One can make feature requests here: https://bugs.kde.org
  • Suggest the above to any 3rd party KDE app developer who has some time time on their hands.
  • Use FileLight to analyze storage usage of your home folder, and delete anything you don’t like to keep (including data you deem sensitive, if the privacy is a concern).

I wished to increase the max depth because with value 2 not all the directories are explored.
I.e.: for the JuK application (juk) are a lot of image files strewed among many ./local/share/icons/ subdirectories, like this

.local/share/icons/Arc-ICONS/apps/16@2x/juk.png

Thus, I set max depth to 4 and let run the function for juk

rnsu juk

… and noticed some unwanted and/or unsafe results:

  • the app are not uninstalled
    it depends surely on the (new) security policy in OpenSUSE Leap 16.0. In my system the command zypper needs root access. with sudo you get only superuser access (wheel) and this is not enough to run zypper.
  • the function delete juk* files in other users’ /home directories
    it caused by the access rights of wheel (due to the sudo command)

For theese reasons I commented out the line sudo zypper -rm $package_name and added

su
zypper -rm $package_name

on the bottom of the function, before # Orphan warning message

but:

  • with su command the Fish shell switch to bash!
    The zypper command in the function does not get executed and consequently the app is not unistalled.
  • and the /home/other usernames/ are explored yet. Even if no file is deleted, you get a lot of questions about. i.e.:
       Delete '/home/otheruser/.hugindata/camlens.db'? (y/n): 

Is the answer = y, the correspondent error message (similar to: not enough rights …) follows.

In order to avoid this I changed

if test "$response" = "y"
        set directories /home ~/.config ~/.cache ~/.local/share

to

if test "$response" = "y"
        set directories /home/geppino ~/.config ~/.cache ~/.local/share

Whereat /geppino is the current username
Neverthless I get scary queries, as

Delete '/home/geppino'? (y/n): 

Questions:

  • Does Delete mean, the subdirectory will be deleted or only explored for searching?
    If /home/geppino could be deleted: what did I make false?
    my current function rsnu
function rnsu
    if test (count $argv) -eq 0
        echo "Usage: rnsu package_name"
        return 1
    end

    # standard Zeile:
    # set package_name $argv[1]
    # Run the zypper command
    # temporarily out
    # sudo zypper -rm $package_name

    # Ask the user if they want to remove the related files
    read -P "Would you like to remove the related configs for \"$package_name\"? (y/n): " response

    if test "$response" = "y"
        set directories /home/geppino ~/.config ~/.cache ~/.local/share
        set found_items 0

        # First pass: display what would be deleted
        for dir in $directories
            set -l matches (find $dir -maxdepth 4 -iname "*$package_name*" 2>/dev/null)
            if test (count $matches) -gt 0
                set found_items 1
                for match in $matches
                    echo "Found: $match"
                end
            end
        end
        
        if test $found_items -eq 1
            # Second pass: collect all matches for individual deletion
            set all_matches
            for dir in $directories
                set matches (find $dir -maxdepth 2 -iname "*$package_name*" 2>/dev/null)
                if test (count $matches) -gt 0
                    set -a all_matches $matches
                end
            end

            set deleted_count 0
            for match in $all_matches
                read -P "Delete '$match'? (y/n): " response
                if test "$response" = "y"
                    echo "Moving to trash: $match"
                    trash -v $match
                    set deleted_count (math $deleted_count + 1)
                end
            end
              if test $deleted_count -gt 0
                echo "Moved $deleted_count item(s) to trash."
            else
                echo "No items were deleted."
            end
        else
            echo "No related files or folders found for \"$package_name\"."
        end
    else
	    echo "No files or directories have been removed or sent to the trash."
    end
    
    # Orphan warning message
    echo "Tip: Check for orphans using zypper info [package name] to find no longer required packages."
    echo "You can re-run \"rnsu\" with these packages individually, but you probably don't need to."
    end

Yes, it woiuld be a good idea. The tool could be integrated in Discover.

there is a thread about the complexity of this idea

where the notion that a fixed set of files can be identified and cataloged is discussed.

it’s not a trivial ask, and what counts as “native” or “core” is not at all clear.

Icons are usually part of icon themes. This means they don’t get added as part of the installation of an application. I have many icons in my icon themes that are from applications I’ve never used or heard about.

These icons, for the most part, should not be included “leftover files to delete”.

Using only su without a command, makes it to so that every command afterwards is done as root. This script/function should not be done as root.

This is because Fish is just a shell for convenience. The root/main shell on most systems is usually bash/zsh. You can change this, but you shouldn’t. It’s not safe for most users to change this.

The reason it switches is like I said above - su does everything as root, and your root shell is bash/zsh.

The original function/script used to delete all of the queries with one y/n question.

However, because sometimes an application might have a similar name, like keepass and keepassxc, it may cause a user to delete files/directories they actually need. So instead, I updated it to ask for every file/directory it finds.

This means that a file found in the keepass directory that is also called keepass.conf will be listed separately and you will get a y/n question for both even if you delete the directory containing the file. This will then throw an error about the missing file since the directory containing the file was deleted. The error can be disregarded.

I have a single-user setup, so I’ve never tested if it’s necessary to add the username to the script. And I’d say that it shouldn’t be necessary because the script should only affect the “working directory”, which is the home directory of the user running the script, which is why, again, using su is not recommended and should be avoided.



EDIT:
To be safe, you can edit the directories to be user-specific like this:

set directories $HOME ~/.config ~/.cache ~/.local/share

Or like this:

set directories $HOME $HOME/.config $HOME/.cache $HOME/.local/share   

I will push an update to my Codeberg that changes it to the second method since this would likely be better for multi-user setups.

DONE.

function rnsu
    if test (count $argv) -eq 0
        echo "Usage: rnsu package_name"
        return 1
    end

    set package_name $argv[1]

    # Detect package manager
    if command -q pacman
        sudo pacman -Rnsu $package_name
    else if command -q apt
        sudo apt purge $package_name
        sudo apt autoremove
    else if command -q zypper
        sudo zypper rm --clean-deps $package_name
    else
        echo "Unsupported package manager"
        return 1
    end

    # Find and remove unneeded leftovers files and directories (dotfiles)
    read -P "Would you like to remove the related configs for \"$package_name\"? (y/n): " response

    if test "$response" = "y"
        set directories $HOME $HOME/.config $HOME/.cache $HOME/.local/share
        set found_items 0

        # First pass: display what would be deleted
        for dir in $directories
            set -l matches (find $dir -maxdepth 2 -iname "*$package_name*" 2>/dev/null)
            if test (count $matches) -gt 0
                set found_items 1
                for match in $matches
                    echo "Found: $match"
                end
            end
        end

        if test $found_items -eq 1
            # Second pass: collect all matches for individual deletion
            set all_matches
            for dir in $directories
                set matches (find $dir -maxdepth 2 -iname "*$package_name*" 2>/dev/null)
                if test (count $matches) -gt 0
                    set -a all_matches $matches
                end
            end

            set deleted_count 0
            for match in $all_matches
                read -P "Delete '$match'? (y/n): " response
                if test "$response" = "y"
                    echo "Moving to trash: $match"
                    trash -v $match
                    set deleted_count (math $deleted_count + 1)
                end
            end

            if test $deleted_count -gt 0
                echo "Moved $deleted_count item(s) to trash."
            else
                echo "No items were deleted."
            end
        else
            echo "No related files or folders found for \"$package_name\"."
        end
    else
        echo "No files or directories have been removed or sent to the trash."
    end
    # Orphan warning message
    echo "Tip: Check for orphans using pacman's -Qdtq argument to find no longer required packages."
    echo "You can re-run \"rnsu\" with these packages individually, but you probably don't need to."
end

@ddnnacheta,

tank a lot for your support!

I’d like to reply to all your comments, but I also have to do someting urgent.
So, at the moment only about the first part. I hope, I can continue still today.

Maybe it ist with Arch Linux something different, however in OpenSUSE the Icons are saved under /home subdirectories not before the first application use.
I have tested that just few minutes ago with an application, I had never used before: Granatier.
Here the results of kfind as image:

Before install

After install, before use

After first launch

In fact, in myrlin (the openSUSE GUI pakage manager) a lot of png files are listed, which are installed with the app.
While install they are saved under /usr subdirectories and on the first application use copied under corresponding /home subdirectories.

Later I’ll write more …

You’re welcome. :handshake:

These aren’t application icons (as in the logo of the application). These are the various buttons (or graphics) you see when the application opens (the GUI buttons).

When you uninstall an application, these graphics usually get deleted as well so long as they don’t exist in your home directory. For the files stored in your home directory - /home or /home/username - these files do not get touched by your package manager simply because they are considered as user data.

So, yes, a gaphical package manager like Myrlyn (and Synaptic) will show you the individual files being installed, including some graphics, but these graphics are unrelated to your icon theme, which is a whole set of icons for almost every app that can run on Linux. Your icon themes are typically stored in usr/share/icons, home/.icons, or .local/share/icons.

The example below shows what I mean.
I have the granatier icon, and until today, I didn’t even know what granatier was.





One More Thing

To clarify: when you use sudo it temporarily gives you access to run a single command with root privileges.

In your case sudo zypper rm --clean-deps $package_name.

Everything else is done as a regular user using find and trash -v.

i’m gonna throw this out there because i just found out about it.

if you are using apt as you package manager you can run

sudo apt -s purge ?config-files

and get a list of applications that you have removed but have left behind some root owned config files in case you ever decide to reinstall.

this can be the start of a program list you can use to hunt down folders / files in your /home folder that contain things you no longer need.

I admit to not have read everything here, but since I can’t find atime mentioned here, I’d like to add for completions sake that if atime is enabled for your home’s filesystem, it is possible to use tools like find to list all files which have not been read for a certain amount of time. This can be a strong indicator for beeing obsolete.

See this for more information: