Coder Social home page Coder Social logo

mikedacre / careful_rm Goto Github PK

View Code? Open in Web Editor NEW
27.0 4.0 8.0 59 KB

A safe wrapper for rm that adds useful warnings and an optional recycle/trash mode

License: MIT License

Shell 11.69% Python 88.31%
zsh coreutils rm bash shell wrapper trash-mode macos macosx linux command-line oh-my-zsh antigen alternative

careful_rm's Introduction

Careful rm

Version: 1.0-beta10

A wrapper for rm that adds more useful warnings and an optional recycle/trash mode

Can be used as a drop-in replacement for rm on any Linux or MacOS system with Python > 2.6. With no arguments or configuration, it will warn you if you delete more than 3 files or any directories, and will print the files and folders to delete to the console when prompting for approval (something rm -I does not do).

All rm commands are implemented here. In addition, passing -c will result in files being trashed/recycled instead of deleted. Applescript is used on MacOS, otherwise the best trash location is chosen (see below). Most files can be restored using GUI tools (e.g. Nautilus/Finder), as the default Trash folders and metadata are used (e.g. Put Back works on Mac).

Note: passing -s will result in files being destroyed with shred and will forcibly override and disable recycle mode.

Ideally, this tool should be symlinked to rm and the file ~/.rm_recycle_home should be created, which will make recycling automatic only for files in your home directory. This will provide a great deal of safety without majorly messing up any sys-admin work.

Contents

Usage

Usage: careful_rm.py [-c] [-f | -i] [-dPRrvW] file ..

Arguments
---------
    -c, --recycle         move to trash instead of deleting (forced on by
                          ~/.rm_recycle)
    -s, --shred           run shred on all files (recursively if directories
                          included) prior to deleting, override recycle
        --direct          force off recycling, even if ~/.rm_recycle exists
        --dryrun          do not actually remove or move files, just print
    -h, --help            display this help and exit

All other arguments passed to rm

Common rm arguments
-------------------
    -f, --force           ignore nonexistent files and arguments, never prompt
    -i                    prompt before every removal
    -I                    prompt once before removing more than three files, or
                          when removing recursively
    -r, -R, --recursive   remove directories and their contents recursively
    -d, --dir             remove empty directories
    -v, --verbose         explain what is being done

For full help for rm, see `man rm`, note that only the '-i', '-f' and '-v'
options have any meaning in recycle mode, which uses `mv`. Argument order does
not matter.

Install as a plugin

Requirements

  • An sh style shell, preferably zsh, dash, or bash
  • Python version 2.6+, no additional modules required

It should work almost everywhere

Note: If anyone can help with a FISH and/or Windows version, that would be great

General Install

With any sh like shell (sh, bash, fish, zsh)

  1. cd ~
  2. git clone [email protected]:MikeDacre/careful_rm.git
  3. echo "source ~/careful_rm/careful_rm.alias.sh" >> .bashrc

ZSH

The ZSH version of this plugin is provided by the careful_rm.plugin.zsh file. In addition to aliasing rm to careful_rm, it also sets a $TRASH variable that updates with every directory change and makes ~trash a named directory that points to $TRASH.

ZSH offers some great ways to install as a plugin and stay up to date, my favorite is antigen, but any of the following methods will work.

If you're using Antigen, just add antigen bundle MikeDacre/careful_rm to your .zshrc file where you're loading your other zsh plugins. You will need to reload ZSH to install the plugin.

  1. mkdir -p ~/oh-my-zsh/custom/plugins
  2. cd ~/oh-my-zsh/custom/plugins
  3. git clone [email protected]:MikeDacre/careful_rm.git
  4. add plugins+=(careful_rm) to the right place in your ~/.zshrc

If you're using Zgen, add zgen load MikeDacre/careful_rm to your .zshrc file where you're loading your other zsh plugins.

Install Script Only

If you want you can install the code directly and handle shell integration yourself. The project can be installed with either pip, or just by directly downloading the script.

To alias the code to rm yourself, you can download and source the careful_rm.alias.sh script, or just add something like this to your ~/.bashrc.

if hash careful_rm.py 2>/dev/null; then
    alias rm="$(command -v careful_rm.py)"
elif hash careful_rm 2>/dev/null; then
    alias rm="$(command -v careful_rm)"
else
    alias rm="rm -I"
fi

Via PIP

This project is on PyPI so you can just install it with pip, but you won't get any shell integration:

pip install careful_rm

Direct Install

You can just put it into your $PATH and use it directly. e.g.:

  1. cd /usr/local/bin
  2. wget https://raw.githubusercontent.com/MikeDacre/careful_rm/master/careful_rm.py

Rationale and Implementation

rm is a powerful *nix tool that simply drops a file from the drive index. It doesn't delete it or put it in a Trash can, it just de-indexes it which makes the file hard to recover unless you want to put in the work, and pretty easy to recover if you are willing to spend a few hours trying (use shred to actually secure erase files).

careful_rm.py is inspired by the -I interactive mode of rm and by safe-rm. safe-rm adds a recycle bin mode to rm, and the -I interactive mode adds a prompt if you delete more than a handful of files or recursively delete a directory. ZSH also has an option to warn you if you recursively rm a directory.

These are all great, but I found them unsatisfying. What I want is for rm to be quick and not bother me for single file deletions (so rm -i is out), but to let me know when I am deleting a lot of files, and to actually print a list of files that are about to be deleted. I also want it to have the option to trash/recycle my files instead of just straight deleting them.... like safe-rm, but not so intrusive (safe-rm defaults to recycle, and doesn't warn).

careful_rm.py is fundamentally a simple rm wrapper, that accepts all of the same commands as rm, but with a few additional options features. In the source code CUTOFF is set to 3, so deleting more files than that will prompt the user. Also, deleting a directory will prompt the user separately with a count of all files and subdirectories within the folders to be deleted.

Furthermore, careful_rm.py implements a fully integrated trash mode that can be toggled on with -c. It can also be forced on by adding a file at ~/.rm_recycle, or toggled on only for $HOME (the best idea), by ~/.rm_recycle_home. The mode can be disabled on the fly by passing --direct, which forces off recycle mode.

The recycle mode tries to find the best location to recycle to on MacOS or Linux, on MacOS it also tries to use Apple Script to trash files, which means the original location is preserved (note Applescript can be slow, you can disable it by adding a ~/.no_apple_rm file, but Put Back won't work). The best location for trashes goes in this order:

  1. $HOME/.Trash on Mac or $HOME/.local/share/Trash on Linux
  2. <mountpoint>/.Trashes on Mac or <mountpoint>/.Trash-$UID on Linux
  3. /tmp/$USER_trash

Always the best trash can to avoid Volume hopping is favored, as moving across file systems is slow. If the trash does not exist, the user is prompted to create it, they then also have the option to fall back to the root trash (/tmp/$USER_trash) or just rm the files.

/tmp/$USER_trash is almost always used for deleting system/root files, but note that you most likely do not want to save those files, and straight rm is generally better.

careful_rm's People

Contributors

mikedacre avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

careful_rm's Issues

Could be worth noting in the docs that simply aliasing is faster

With the plugin in my zshrc my startup timings look something like this:

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    1         336.87   336.87   41.83%    336.87   336.87   41.83%  chpwd_trash
 2)    1         778.28   778.28   96.65%    108.21   108.21   13.44%  zgen-init
 3)    1          83.84    83.84   10.41%     83.69    83.69   10.39%  _zsh_nvm_lazy_load
 4)    1          59.25    59.25    7.36%     59.25    59.25    7.36%  _zgen-check-for-updates
 5)    4         131.80    32.95   16.37%     47.98    12.00    5.96%  pmodload
 6)    2          47.20    23.60    5.86%     47.20    23.60    5.86%  compinit
 7)    3          26.29     8.76    3.26%     26.29     8.76    3.26%  mkdir
 8)    1          21.75    21.75    2.70%     21.52    21.52    2.67%  _zsh_highlight_load_highlighters
 9)    1          18.32    18.32    2.28%     18.32    18.32    2.28%  prompt_pure_state_setup
10)    2          18.14     9.07    2.25%     18.14     9.07    2.25%  promptinit
11)    1          11.00    11.00    1.37%     11.00    11.00    1.37%  _zsh_highlight_bind_widgets
12)    2          14.02     7.01    1.74%      7.11     3.55    0.88%  async
13)    1           6.91     6.91    0.86%      6.91     6.91    0.86%  async_init
14)    2          37.33    18.66    4.64%      3.68     1.84    0.46%  prompt_pure_setup
15)   14           3.24     0.23    0.40%      3.24     0.23    0.40%  (anon)
16)   12           2.64     0.22    0.33%      2.64     0.22    0.33%  add-zsh-hook
17)    3           1.12     0.37    0.14%      1.12     0.37    0.14%  is-at-least
18)    3           0.78     0.26    0.10%      0.68     0.23    0.08%  add-zle-hook-widget
19)   22           0.44     0.02    0.05%      0.44     0.02    0.05%  put_template
20)    1          38.37    38.37    4.77%      0.29     0.29    0.04%  set_prompt
21)    1          38.60    38.60    4.79%      0.23     0.23    0.03%  prompt
22)    1           0.20     0.20    0.02%      0.17     0.17    0.02%  zgen
23)    1           0.15     0.15    0.02%      0.15     0.15    0.02%  _zsh_nvm_has
24)    2           0.05     0.02    0.01%      0.05     0.02    0.01%  put_template_var
25)    1           0.03     0.03    0.00%      0.03     0.03    0.00%  is-callable
26)    1           0.03     0.03    0.00%      0.03     0.03    0.00%  zgen-saved
27)    1           0.02     0.02    0.00%      0.02     0.02    0.00%  put_template_custom

That first column and %-column is interesting to look at. Looking deeper zgen-init also spends time mostly on chpwd_trash.

With a simple alias to the python script, instead of the full plugin, my startup looks like this:

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    4         216.78    54.20   44.67%     86.15    21.54   17.75%  pmodload
 2)    1          83.53    83.53   17.21%     83.42    83.42   17.19%  _zsh_nvm_lazy_load
 3)    1          75.15    75.15   15.49%     75.15    75.15   15.49%  _zgen-check-for-updates
 4)    2          47.83    23.92    9.86%     47.83    23.92    9.86%  compinit
 5)    1         467.79   467.79   96.40%     43.60    43.60    8.99%  zgen-init
 6)    1          27.63    27.63    5.69%     27.63    27.63    5.69%  prompt_pure_state_setup
 7)    2          24.82    12.41    5.12%     24.82    12.41    5.12%  promptinit
 8)    2          36.88    18.44    7.60%     20.36    10.18    4.20%  async
 9)    1          16.53    16.53    3.41%     16.53    16.53    3.41%  async_init
10)    3          16.46     5.49    3.39%     16.46     5.49    3.39%  mkdir
11)    1          14.10    14.10    2.91%     13.87    13.87    2.86%  _zsh_highlight_load_highlighters
12)    1          12.97    12.97    2.67%     12.97    12.97    2.67%  _zsh_highlight_bind_widgets
13)   14           6.32     0.45    1.30%      6.32     0.45    1.30%  (anon)
14)   12           3.21     0.27    0.66%      3.21     0.27    0.66%  add-zsh-hook
15)    2          70.64    35.32   14.56%      2.88     1.44    0.59%  prompt_pure_setup
16)    3           1.79     0.60    0.37%      1.58     0.53    0.32%  add-zle-hook-widget
17)    3           0.78     0.26    0.16%      0.78     0.26    0.16%  is-at-least
18)   22           0.75     0.03    0.16%      0.75     0.03    0.16%  put_template
19)    1          71.87    71.87   14.81%      0.40     0.40    0.08%  set_prompt
20)    1          72.06    72.06   14.85%      0.19     0.19    0.04%  prompt
21)    1           0.19     0.19    0.04%      0.16     0.16    0.03%  zgen
22)    1           0.11     0.11    0.02%      0.11     0.11    0.02%  _zsh_nvm_has
23)    2           0.04     0.02    0.01%      0.04     0.02    0.01%  put_template_var
24)    1           0.03     0.03    0.01%      0.03     0.03    0.01%  zgen-saved
25)    1           0.02     0.02    0.00%      0.02     0.02    0.00%  is-callable
26)    1           0.01     0.01    0.00%      0.01     0.01    0.00%  put_template_custom

Much better! In milliseconds, for me, it made ~800ms -> ~500ms.

Options by default [Question]

I have added the following lines in my .zshrc:

    if hash careful_rm.py 2>/dev/null; then
        alias rm="$(command -v careful_rm.py)"
    else
        alias rm="rm -I"
    fi

as described in the help file ($ rm -h).
Now
$ rm -cviI
and
$ careful_rm.py -cviI
work fine but I would like to have these options by default when I simply run $ rm.
How can it be done?
The alias
alias rm="careful_rm.py -cviI"
does not work.

Add shred

It should be pretty easy to add a --shred mode that forces off recycling, calls shred and then rm.

Skip Applescript on MacOS

The code works fine on Mac, but it is slow because applescript is slow, I think there should be a way to bypass applescript by editing the .DS_Store files, but I haven't bothered yet as there isn't good documentation on how this even works.

Windows Support

The code should hypothetically work fine on a Windows *nix environment like Cygwin or the new Windows bash shell, but I don't have Windows and can't test it. If anyone wants to take a whack at adding Windows support, that would be great.

check_output calls run with invalid get param

Just tried installing this in Oh-My-Zsh on macOS 10.13.6 (17G65) but starting a new shell shows a Python stack trace...

  OSA = check_output('command -pv osascript', shell=True).strip()
File "/Users/andy/.oh-my-zsh/custom/plugins/careful_rm/careful_rm.py", line 163, in check_output
  _, stdout, _ = run(cmd, shell=shell, check=True, get=True)
File "/Users/andy/.oh-my-zsh/custom/plugins/careful_rm/careful_rm.py", line 130, in run
  'get must be one of {0} is {1}'.format(get_options, get)
ValueError: get must be one of ['all', 'stdout', 'stderr', 'code', None] is True```

Digging through the code, it looks like `check_output` is passing `get=True` to the run command: https://github.com/MikeDacre/careful_rm/blob/master/careful_rm.py#L161 which immediately raises the ValueError.

The output of `command -pv osascript` on my system is `/usr/bin/osascript` but I can't quite work out what we should be passing to run's `get` param, otherwise I'd have done a PR for you.

Empty directory option not handled

Passing in -d still prompts to include the -r flag despite the target directory being empty. For example:

$ mkdir empty
$ rm -d empty
Directories ['empty'] included but -r not sent

Add -r, ignore dirs, or cancel? [add/ignore/CANCEL] ignore

No files or folders to delete

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.