You are not logged in.

#1 2007-10-18 07:13:23

bsdson.tw
Member
From: Taiwan
Registered: 2005-05-06
Posts: 161

Bash implementation to Freedesktop's Trash standard

This is a command-line tool to remove files, which implements the Free-desktop's Trash standard.

The original discussion is at
http://bbs.archlinux.org/viewtopic.php?id=31017

And one buddy called skymt had also made another implementation depends on Python at
http://aur.archlinux.org/packages.php?d … =1&ID=9874

Because I can not do Python programming to fix some annoyances in it,
I tried to make my own version which depends only on Bash. (almost)

And here are the latest versions:
[trash]

#!/bin/bash

# http://www.ramendik.ru/docs/trashspec.html

# home_trash_can=$XDG_DATA_HOME/Trash
# $home_trash_can/info
# $home_trash_can/files
# create XXX.trashinfo first
# [Trash Info]
# Path=$org_location/$org_filename # absolute path name
# DeletionDate=YYYY-MM-DDThh:mm:ss

# requirement:
# realpath

# [output]
# normal: only show the files with different trash names (which mean name space conflicts)
# quiet: -q no output
# verbose: -v output each file
# [interactive mode]
# no interactive mode, cause the trash can always be recovered
# [recursive mode]
# no recursive mode, reasoned as above
# [version]
# [help]

# bug:
# 1. trash by su-ed root will move trash to the user's trash-can

# -------------------------------------------------------







# init
deletion_date=$(date +%Y-%m-%dT%H:%M:%S)
home_trash_can=$XDG_DATA_HOME/Trash
output=normal

# parse arguments
if [ "--version" = "$1" ]; then
    echo "@todo: version"
    exit 0
elif [ "--help" = "$1" -o 0 -eq "$#" ]; then
    echo "@todo: help"
    exit 0
elif [ "-v" = "$1" ]; then
    output=verbose
    shift
elif [ "-q" = "$1" ]; then
    output=quiet
    shift
fi

# check
if [ ! -d "$home_trash_can/info" -o ! -r "$home_trash_can/info" -o ! -w "$home_trash_can/info" -o ! -x "$home_trash_can/info" ]; then
    # exception handling
    echo "Something wrong with directory $home_trash_can/info..."
    exit 4
fi

if [ ! -d "$home_trash_can/files" -o ! -r "$home_trash_can/files" -o ! -w "$home_trash_can/files" -o ! -x "$home_trash_can/files"]; then
    # exception handling
    echo "Something wrong with directory $home_trash_can/files..."
    exit 6
fi

#
for file in "$@"; do

    if [ verbose = "$output" ]; then
        echo "removing $file..."
    fi

    # check
    abs_path_name=$(realpath -s "$file")
    org_location=$(dirname "$abs_path_name")
    org_filename=$(basename "$abs_path_name")
    if [ verbose = "$output" ]; then
        echo " abs_path_name=$abs_path_name"
    fi

    if [ ! -e "$file" -o ! -x "$org_location" -o ! -w "$org_location" ]; then
        if [ quiet != "$output" ]; then
            echo "$file: file does not exist, or can not be moved to the trash-can!"
        fi
    fi

    #
    ext=""
    while [ -e "$home_trash_can/info/$org_filename$ext.trashinfo" ]; do
        #sleep .$RANDOM
        ext=$(($ext + 1))
    done

    #
    info="$home_trash_can/info/$org_filename$ext.trashinfo"
    echo "[Trash Info]" > "$info"
    echo "Path=$abs_path_name" >> "$info"
    echo "DeletionDate=$deletion_date" >> "$info"

    mv "$file" "$home_trash_can/files/$org_filename$ext"&

    #
    if [ -n "$ext" -a quiet != "$output" ]; then
        echo " $file moved to trash-can with a new name: $org_filename$ext"
    fi
done

the above script is used to remove files, while the below script is used to list all the trashes, and to do recover (todo)

[trash_can]

#!/bin/bash

# trash-can
# 10/17/2007
# by Henry

# init
home_trash_can=$XDG_DATA_HOME/Trash
operation=list # recover(-r), check(-c)
select=almost
output=classify # long(-l)
sort=none # size(-s), date(-d), name(-n), path+name(-p), type(-t)

# parse arguments
while echo "$1" | grep -q "^-"; do
    case "$1" in
        "-l")
        output=long
        ;;
        "-r")
        operation=recover
        ;;
        "-c")
        operation=check
        ;;
        "-s")
        sort=size
        ;;
        "-d")
        sort=date
        ;;
        "-n")
        sort=name
        ;;
        "-p")
        sort="path+name"
        ;;
        "-t")
        sort=type
        ;;
        *)
        break
        ;;
    esac
    shift
done

# check
if [ ! -d "$home_trash_can/info" -o ! -r "$home_trash_can/info" -o ! -w "$home_trash_can/info" -o ! -x "$home_trash_can/info" ]; then
    # exception handling
    echo "Something wrong with directory $home_trash_can/info..."
    exit 4
fi

if [ ! -d "$home_trash_can/files" -o ! -r "$home_trash_can/files" -o ! -w "$home_trash_can/files" -o ! -x "$home_trash_can/files" ]; then
    # exception handling
    echo "Something wrong with directory $home_trash_can/files..."
    exit 6
fi

# main
if [ recover = $operation ]; then
    echo "Operation:$operation is currently not implemented!"

elif [ check = $operation ]; then
    # simple check based on "files" (not "info")
    IFS="
    "
    for file in $(ls -1 "$home_trash_can/files"); do
        if [ ! -e "$home_trash_can/info/$file.trashinfo" ]; then
            echo $file
        fi
    done

elif [ list = $operation ]; then
    org_IFS="$IFS"
    IFS="
    "
    for file in $(ls -1 "$home_trash_can/info"); do
        tmp=$home_trash_can/files/${file%.trashinfo}
        tmp1=$(ls -Fd "$tmp")
        if [ 0 -ne $? ]; then
            continue
        fi

        if [ long = $output ]; then
            echo -n "$(grep DeletionDate "$home_trash_can/info/$file" | cut -d = -f 2)"
            tmp2=$(du -hs $tmp | cut -f 1)
            echo -n "    $tmp2"
            tmp3=$(dirname "$(grep Path "$home_trash_can/info/$file" | cut -d = -f 2)")
            echo -n "    $tmp3/"
        fi

        echo $(basename "$(grep Path "$home_trash_can/info/$file" | cut -d = -f 2)")${tmp1#$tmp}
    done
    IFS="$org_IFS"
fi

# [usage]
# (usage refer to command "ls")
# (select)
# -A: almost all, do not list implied . and ..
# (display)
# -F: classify, append indicator (one of */=>@|) to entries
# (file information)
# -l: use a long listing format
# --time=WORD: with -l, show time as WORD instead of modification time: atime -u, access -u, use -u, ctime -c, or status -c; use specified time as sort key if --sort=time
# (sort)
# --group-directories-first: group directories before files
# -r: reverse order while sorting
# -S: sort by file size
# --sort=WORD: sort  by  WORD  instead of name: none -U, extension -X, size -S, time -t, version -v
# [deleted file information]
# real name
# real path
# deletion date
# type (regular file, directory, device node, symbolic link, etc)
# size
# ---------------------------------------------------------------------

Offline

#2 2011-04-28 04:22:26

semeion
Member
From: Brazil
Registered: 2008-10-20
Posts: 65

Re: Bash implementation to Freedesktop's Trash standard

Nice!

i was thinking.... Is possible integrate this 2 functions in openbox pipedmenu?

=p

Offline

#3 2011-04-28 12:33:10

Damnshock
Member
From: Barcelona
Registered: 2006-09-13
Posts: 414

Re: Bash implementation to Freedesktop's Trash standard

Nice initiative smile

You implementation could be improved though. In fact, I've noticed a problem with files if they happen to have spaces on its filename. (this is usually due to lack of proper quoting ).

Anyway, first quick look at your script:

for file in $(ls -1 "$home_trash_can/files"); do

Never ever do that

for file in "$home_trash_can/files/\*" ; do

or you can as well use "find"

I'll look deeper into the script this weekend. Sounds like a fun project!!!

Regards


My blog: blog.marcdeop.com
Jabber ID: damnshock@jabber.org

Offline

#4 2011-04-28 12:50:11

Stalafin
Member
From: Berlin, Germany
Registered: 2007-10-26
Posts: 617

Re: Bash implementation to Freedesktop's Trash standard

Great, just today I was talking to a friend about how I (repeatedly!) rm'ed my entire home directory by doing something stupid like $ rm -r abcd * , where for some reason I hit the space bar...

I will look into the thing as well! Thanks a lot!

As to what Damnshock mentioned there:
You should have a look at the bash wiki at [1]. The guy also provides a very nice FAQ at [2] and finally, the so called Bash pitfalls at [3], which actually covers a common mistake Damnshock mentioned. Really helpful place which helped (and still helps!) me to learn bash.

1: http://mywiki.wooledge.org/BashGuide
2: http://mywiki.wooledge.org/BashFAQ
3: http://mywiki.wooledge.org/BashPitfalls


EDIT: You have referenced the trash [4] application by skymt: in the comment section of his AUR entry he mentions that people should rather use trash-cli [5]. Did you have a look at that one as well? It seems to be rather up-to-date compared to trash, and maybe the features you were missing can be found in there?

4: http://aur.archlinux.org/packages.php?ID=9874
5: http://aur.archlinux.org/packages.php?ID=19076


EDIT 2: OMG, did you guys notice that this thread is from 2007?! Mods, please close...

Last edited by Stalafin (2011-04-28 12:54:44)

Offline

#5 2011-04-29 10:49:08

Damnshock
Member
From: Barcelona
Registered: 2006-09-13
Posts: 414

Re: Bash implementation to Freedesktop's Trash standard

Wow, I did not realize this was a post from 2007 :S


My blog: blog.marcdeop.com
Jabber ID: damnshock@jabber.org

Offline

Board footer

Powered by FluxBB