0

Environment

System: Linux Mint 19 Cinnamon.

Shell: Bash version 4.4.19(1).


Problem

Along with hundreds of testing scenarios, I must have created countless of temporary installation directories with files as their content, which I need to delete every time manually. It looks like this:

$ ls --group-directories-first --classify

test1/  test2/  testA/  testFin/  decrypt-file-aes256*  encrypt-file-aes256*  Makefile  openssl-encryption.tar.xz  openssl-encryption.tar.xz.asc  SHA512SUM

I want to automatize this cleanup process.


Progress

I have found the find command can be very useful, e.g.:

find . -maxdepth 1 -type d -exec rm -rf {} +

This, in my early tests from the terminal, showed to be working, but before I put it into my Makefile, clean target, I want to ask if there is any safety measure I should take into account?


That example, however, produces a small error:

rm: refusing to remove '.' or '..' directory: skipping '.'

How to go about being more specific here?


Current re-factored 'clean' Makefile target

clean:

    @echo; tput bold; tput setaf 3; echo Target: $@; tput sgr0; echo

    @if [ $$(id --user) -eq 0 ]; then \
        tput bold; tput setaf 1; echo "ERROR: Target '$@' has to be run as normal user!"; tput sgr0; echo; exit 1; \
    fi

    @if [ ! -f .safeclean-$(distrib_name) ]; then \
        tput bold; tput setaf 1; echo "ERROR: Target '$@' has to be run from within its Makefile's directory!"; tput sgr0; echo; exit 1; \
    fi

    @ls -l | grep '^d' > /dev/null || echo "There are no more directories."

    @for dir in *; do \
        if [ -d "$$dir" ]; then rm --force --recursive --verbose "$$dir"; fi \
    done

    @rm --force --verbose $(distrib_name).tar.xz $(distrib_name).tar.xz.asc

    @echo; tput bold; tput setaf 2; echo "Ok. Directory clean successful."; tput sgr0

Example output (visual)

Example output (visual)

2

First of all, please be extra careful before doing find + rm in a Makefile.

Having said that, you may find it easier to script it:

myclean:
        test -f .safefile && \
        for fn in * ; do \
                test -d "$$fn" && rm -rf "$$fn" ; \
        done

Where .safefile is a file that should exist in your top-level directory. It will ensure that you don't run this from a different location by mistake.

The additional benefit is that you can also add logic to it when you need to.

  • The loop could possibly be removed and replaced by rm -rf */ unless there are several thousands of directories. If the directories are all called test* (as in the question), then rm -rf test*/ would do it. – Kusalananda Oct 15 '18 at 6:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.