Search code examples
androidsh

Android shell script to remove all files and folders in a directory except one


Right now I am using rm -r /blaa/* to delete all folders and files in the blaa directory. What I am looking for is a way to remove all folders and files in the blaa directory except if the folder is named abc.

Any ideas?


Solution

  • In Linux:

    There are many ways to this; however I believe the best way to do this is to simply use the "find" tool.

    find ! -iname "abc" -exec rm -rf {} \;
    

    We can easily find and delete the every file and folder that is not named "abc".

    find      - to find files
    ! -iname  - to filter files/folders, the "!" means not
    -exec     - to execute a command on every file
    rm -rf    - remove/delete files -r for folders as well and -f for force
    "{} \;"   - allows the commands to be used on every file
    

    In Android:

    Since you can't use "rm -rf" and when you use "rm -r" it will delete the folder "." which ends up deleting everything.

    I am guessing you have "root" on your phone because you can use the "find" tool.

    find ! -iname "abc" | sed 1d | xargs rm -r
    
    find      - to find files
    ! -iname  - to filter files/folders, the "!" means not
    |         - pipe sends data to next command
    sed       - replace text/output
    "1d"      - removes first line when you do "find ! -iname" by itself
    xargs     - runs commands after pipe
    rm -r     - remove/delete files, "-r" for recursive for folders
    

    Edit: Fixed and tested in Android

    You can easily change this to suite your needs, please let me know if this helps!


    The Adopted Solution

    ...and the final hoorah... This is what worked for the use case (helps to sum up the comments below as well):

    find ! -iname "abc" -maxdepth 1 -depth -print0 | sed '$d' | xargs -0 rm -r;
    

    Notes:

    • -depth — reverses the output (so you dont delete sub-dirs first
    • -maxdepth 1 — kind of voids the use of -depth, but hey... this says only output contents of the current directory and not sub-dirs (which are removed by the -r option anyway)
    • -print0 and -0 — splits on line feeds instead of white space (for dirs with space in the name)
    • sed "$d" — says to remove the last line (cause its now reversed). The last line is just a period which including would make the call delete everything in the directory (and subs!)

    I am sure someone can tighten this up, but it works and was a great learning op!

    Thanks again to Jared Burrows(and the Unix community in general — go team!) — MindWire