3

Hi I'm creating a recycle bin script with the command name 'safe_rm'. I was wondering, how can I prevent the script from deleting its own file. I believe the readlink command is one solution however I'm not sure how to write it within the script.

Here is my current code

while [ $# -ne 0 ]
   do

    if [ ! -e "$1" ] ; then
            echo "File not found."
    elif [ -d "$1" ] ; then
            echo "Error. You have entered a directory."
    elif [ $1 = $(readlink -e ~/project/safe_rm) ] ;
            echo "Attempting to delete safe_rm - operation aborted"
            exit 0

    else
    inode=` ls -i $1 | cut -d" " -f1 `
    echo $1_$inode:$(readlink -e $1) >> /home/j.t/.restore.info
    mv $1 /home/j.t/deleted/$1_$inode

    echo "File '$1' has been moved to the recycle bin."
    fi

shift
done

The code which needs modifying is on line 8.

1

You're just one step short of a working solution. Canonicalize the variable, and you're done:

elif [ "$(readlink -e "$1")" = "$(readlink -e ~/project/safe_rm)" ] ;

I wrap everything into quotes because paths may contain spaces. Note that you don't have to escape the quotes inside subshell ($(…) thingy). Thanks to @glenn jackman for this correction.

2
  • Good advice about quoting the results. However, keep your command substitution syntax consistent: elif [ "$(readlink -e "$1")" = "$(readlink -e ~/project/safe_rm)" ] -- within the parantheses, you are in a subshell, so you don't need to escape the quotes. – glenn jackman May 2 '16 at 20:09
  • Wow, I didn't even know about quoting in parentheses. Thanks! – Alexander Batischev May 3 '16 at 8:44
1

If you are using readlink -e, that assumes GNU coreutils. But using ls to obtain the inode value is indirect. By using stat (also from the same coreutils package), you can get the inode value directly. If you limit the comparison to inodes, you can also prevent symbolic links which you may have setup to point to your script from being removed.

Here is an example:

#!/bin/sh
mynode=$(stat --printf='%i' $(readlink -e "$0"))
while [ $# -ne 0 ]
   do
    if [ ! -e "$1" ] ; then
            echo "File not found."
    elif [ -d "$1" ] ; then
            echo "Error. You have entered a directory."
    else
        itnode=$(stat --printf='%i' "$1")
        if [ $mynode = $itnode ] ; then
            echo "Attempting to delete $0 - operation aborted"
            exit 0
        fi    

        echo "$1_$itnode:$(readlink -e "$1")" >> /home/j.t/.restore.info
        mv "$1" "/home/j.t/deleted/$1_$itnode"

        echo "File '$1' has been moved to the recycle bin."
    fi

    shift
done
0

chattr can inhibit anyone but root from being able to delete a file, even a file stored in the trash bin.

As root

chattr +i /path/to/safe_rm

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.