Demo Video:
Try it out:
git clone https://github.com/Songtech-0912/safe-delete.git ~/.safe-delete && ~/.safe-delete/install.sh
It is so often the case that I misuse the rm
command. Take this, for example:
> rm package*
# Result: deleted package.json and package-lock.json
Ahem...I just deleted my precious package.json
while trying to delete my package-lock.json
(and forgetting the other file). Or what about this:
> ls | grep hello.txt
hello.txt
> rm -rf helo.txt
# no warning
> rm -rf helllo.txt
# no warning
> rm -rf hello.tx
# still no warning!
Unfortunately, the file is still there, and I have no idea that I didn't delete it. Or if this happens:
> rm -rf node_modules
# rm: cannot remove 'node_modules': Is a directory
Arrgh...you get the idea.
And these little things add up.
We programmers have to use the rm
command dozens of times a day. Every time we do something silly, wrong or even dangerous, the rm
command is unable to correct our mistakes. What's more, the rm
command is a silent command. If you run rm -rf
, there's nothing stopping you from deleting your entire codebase - which you forgot to push to GitHub for some lazy reason.
That is why I created delete.py.
In most ways delete.py
resembles the rm
command, it just does things in a safer way. After all, it is basically a wrapper around rm
, with some improvements using python. These include:
- Colorful commands with red/green/bold colors to keep things clear
- Avoiding the
is a directory
nonsense ofrm
- Showing how to solve a particular error if you face one
- Allowing you to move something to trash rather than to permanently remove it
- Cancel any operation at any time with
Ctrl C
- Confirmation bars that are enough to catch your attention but not enough to affect your productivity
- (Opinionated) Making moving to trash default
- (Opinionated) Asking for confirms, and always setting the less destructive version as default
- (Opinionated) Having only one "true" command line argument so you can't mistype an argument and shoot yourself in the foot
Notably, while delete.py
technically "absorbs" any command other than -ff
, so you could really pass any argument to it (such as -4u
or -m8
), it only has one real commandline flag: -ff
. The two f's stand for "forced force" which is why I added it.
Usage is very simple:
delete [-ff] <your-file-or-folder>
# e.g. delete ~/Downloads/Bloated-useless-stuff.gif
This command can be made even more simple if you read about using aliases down below:
To install this application, run this one-liner command:
curl https://raw.githubusercontent.com/Songtech-0912/Safe-Delete/master/install.sh | bash
export $TRASH = ~/.local/share/Trash
What this basically does is to run my install
script after downloading it from Github. This ensures you'll always have the latest, most up-to-date version of delete.py
available from your computer. Next, it sets your Trash directory - if a trash folder does not exist then one will be created, but you can configure it to your liking.
- You may need to open a new terminal after running the command for
delete
to start working - You will need to make sure that there is a file called
~/.profile
in your home directory
First, clone the source code from GitHub:
git clone https://github.com/Songtech-0912/Safe-Delete.git && cd Safe-Delete
Then, copy the python script to /usr/local/bin
:
sudo cp delete.py /usr/local/bin/delete
Setup aliases:
# if you don't have a ~/.profile, create one
echo "export PATH=/usr/local/bin:$PATH" > ~/.profile
echo "alias rm='delete'" > ~/.zshrc # if you are using zsh shell (most MacOS)
echo "alias rm='delete'" > ~/.bashrc # if you are using bash shell (most GNU/Linux)
To start developing this application, run this command:
git clone https://github.com/Songtech-0912/Safe-Delete.git && cd Safe-Delete
bash manual_install.sh
To fully make use of delete.py
however, I would recommend you alias it as rm
. For those that don't know, an alias is like a command substituter, so when you type in one command, like this one:
> rm -rf my_useless_bloated_1GB_node_modules_folder
The alias actually runs this command in the background:
> delete node_modules
(In this case, the aliases used were alias rm='delete'
and alias node_modules='my_useless_bloated_1GB_node_modules_folder'
)
This is something that the install script will do by default, but if you are manually installing it, you will need to do this yourself. Just open your ~/.bashrc
file (if you use bash), or ~/.zshrc
file (if you use zsh)*, and add in this line (no space before or after the equal sign):
alias rm='delete'
*: Fish shell aliases are something I don't know much about, please inform me if you are experienced with it!
If you do this, your old muscle memory of rm
doesn't need to be forcibly retaught to use delete
instead.
This project has a fair number of bugs that are being fixed. However, you can be sure that more and more bugs will get fixed as the project matures!
- Bug with giving too many arguments fixed
- Bug with a filename with spaces fixed (so you can now say
delete "hello world.txt"
) - Bug with
\
in filenames fixed (sodelete my\ file
is now valid) - Fix not deleted file bug: check if file has actually been deleted when
-ff
is used
- Implement support for safe globbing (e.g.
delete *.py
) but also make sure that the user knows how many files they are deleting in this way (e.g. tell the user "you are deleting 3 files with extension.py
, here are their filenames") - Make it cross-platform (by supporting Windows as well)
- Auto-detect the user's system Trash folder on first launch, or create one if one does not exist already
- Add in an option to clean the Trash folder such as
delete -c
which would empty the trash folder - this avoids the Trash folder getting cluttered with items thatdelete
"safely" sent to Trash and didn't permanently delete- Also warn the user if their Trash folder has > 1 GB of files
Deleting multiple files, or using certain expressions that rm
provides isn't always going to work with delete.py
. For instance, the wildcard symbol (*) which is used to delete multiple files only deletes the first file of the sequence using delete.py
. This is planned to be fixed soon.