trash-cli icon indicating copy to clipboard operation
trash-cli copied to clipboard

I have made a new partition on a secondary drive, owned by my main user. I can use trash-put, but trash-empty does not remove the files.

Open krompus opened this issue 10 years ago • 13 comments
trafficstars

The drive is mounted to /mnt/blue , and I see /mnt/blue/.Trash/files and /mnt/blue/.Trash/info have been created. I see all of the files in there, but trash-empty doesn't clear them. I'm guessing this has something to do with permissions and ownership. Any ideas of how to fix this?

Thanks for the great program, by the way! I use it with ranger instead or rm, and it's been wonderful!

krompus avatar Nov 07 '15 23:11 krompus

I'm seeing the same issue. It seems that trash-empty only operates on ~/.local/share/Trash.

DarwinAwardWinner avatar Jan 26 '17 07:01 DarwinAwardWinner

@DarwinAwardWinner, @krompus

Please provide more information:

  • Which version of trash-cli are you using?
  • Are you using the latest available version of trash-cli?
  • Which command exactly you typed?
  • Does trash-empty will output any message?

andreafrancia avatar Jan 26 '17 12:01 andreafrancia

Here's a demonstration. As shown by the df command, $HOME/syncthing is its own filesystem (actually a ZFS dataset), and it gets its own trash dir separate from the one in $HOME.

ryan@mneme:~/syncthing⟫ trash-put --version
trash-put 0.17.1.14
ryan@mneme:~/syncthing⟫ df -h .
Filesystem                    Size  Used Avail Use% Mounted on
rpool/fs/home/ryan/syncthing  1.2T  115G  1.1T  10% /home/ryan/syncthing
ryan@mneme:~/syncthing⟫ touch something
ryan@mneme:~/syncthing⟫ trash-put something
ryan@mneme:~/syncthing⟫ tree .Trash-1000/
.Trash-1000/
├── files
│   └── something
└── info
    └── something.trashinfo

2 directories, 2 files
ryan@mneme:~/syncthing⟫ trash-empty
ryan@mneme:~/syncthing⟫ tree .Trash-1000/
.Trash-1000/
├── files
│   └── something
└── info
    └── something.trashinfo

2 directories, 2 files

DarwinAwardWinner avatar Jan 26 '17 20:01 DarwinAwardWinner

I'm seeing the same thing on my system. /home/protist/foo gets trashed to /home/.Trash/1000. However, trash-empty 7 won't empty this trash. My setup is described in issue #38.

I also tried trash-empty --trash-dir /home/.Trash/1000 7. This did empty the right trash, but did not respect the 7, instead trashing everything regardless of trash date.

protist avatar Aug 09 '17 00:08 protist

Same problem...

$ df -h
/dev/sda4        28G   13G   13G  50% /
/dev/sda5        77G   53G   20G  73% /opt
/dev/sdb8       114G   13G   95G  12% /home
$ ls -la /opt |grep -i trash
drwxrwxrwt  3 root root  4096 Aug 25 14:09 .Trash/
$ ls -la ~/.local/share |grep -i trash
drwxr-xr-x  4 yf yf  4096 Aug 22 14:31 Trash/
$ trash --verbose /home/yf/a.txt
trash: Volume of file: /home
trash: Trash-dir: /home/yf/.local/share/Trash from volume: /home
trash: '/home/yf/a.txt' trashed in ~/.local/share/Trash
$ trash --verbose /opt/playonlinux/b.txt
trash: Volume of file: /opt
trash: Trash-dir: /home/yf/.local/share/Trash from volume: /home
trash: Trash-dir: /opt/.Trash/1000 from volume: /opt
trash: '/opt/playonlinux/b.txt' trashed in /opt/.Trash/1000
$ trash-list 
2017-08-25 15:36:57 /home/yf/a.txt
$ trash-empty
$ ls /opt/.Trash/1000/files
b.txt

abviously, trash-list and trash-empty can not identify the trash directory except ~/.local/share/Trash

yinflying avatar Aug 25 '17 07:08 yinflying

Same:

trash-empty/trash-list never works inside other partitions for me, it doesn't matter which filesystem, I've tried both ext4 and ntfs. I had rm as an alias to trash-put but in truth it's quite annoying, because anytime I do a rm (trash-put in fact) on a file in whatever partition I have, the files get moved to a /.Trash-1000 directory at the partition that file resides, but trash-empty/trash-list just recognizes the trash of my system's partition, not the others, so I can't forget to delete those /.Trash-1000 directories with /bin/rm.

oblitum avatar Jan 06 '18 22:01 oblitum

Possibly "dirty" workaround for your bashrc:

trash-empty(){
    local mountpoint
    for mountpoint in $( cat /proc/mounts | awk '{ print $2; }' ); do
        if [ -d "$mountpoint/.Trash/$UID" ]; then command rm -r "$mountpoint/.Trash/$UID/"; fi
        if [ -d "$mountpoint/.Trash-$UID" ]; then command rm -r "$mountpoint/.Trash-$UID/"; fi
    done
}

"dirty": personally I don't see any cons for this method, but it basically is a total reprogramming of trash-empty. And if the original trash-empty wasn't implemented in this short manner, then there must be some problem with it which I don't see, yet.

mxmlnkn avatar Jan 06 '18 22:01 mxmlnkn

@mxmlnkn But this doesn't look like it takes the trash-empty argument for the number of days. (See man trash-empty.)

protist avatar Jan 13 '18 02:01 protist

@protist Ah, I didn't even know trash-empty had that kinda functionality and never needed it, but here is my take on how to implement even that with bash:

trash-empty()
{
  local mountpoint folder dry
  local ndays=$1
  if [ "$1" == '-d' ] || [ "$2" == '-d' ]; then dry=echo; fi
  for mountpoint in $( cat /proc/mounts | awk '{ print $2; }' ); do
    for folder in ".Trash/$UID" ".Trash-$UID"; do # '$RECYCLE.BIN'
      if [ -d "$mountpoint/$folder" ]; then
        echo "Deleting '$mountpoint/$folder/' ..." 1>&2
        if [ "$ndays" -eq "$ndays" ] 2>/dev/null && [ "$ndays" != 0 ] && [ -d "$mountpoint/$folder/info/" ]; then
          # assuming that file modification date for .trashinfo files is the same as the DeletionDate stored inside that file
          # note that -mtime +0 will find all files older than 24h and +1 all files older than 2 days, ...
          find "$mountpoint/$folder/info/" -mtime "+$(( ndays-1 ))" -name '*.trashinfo' -print0 |
          sed -rz "s|^(.*)/${folder//./\\.}/info/(.*)\.trashinfo$|\1$folder/info/\2.trashinfo\x00\1$folder/files/\2|" |
          xargs -0 $dry 'rm' -r
        else
          $dry command rm -r "$mountpoint/$folder/"
        fi
      fi
    done
  done
}

There is a dry-run option when appending -d like trash-empty 2 -d. Well, but don't run the script if you don't understand it and especially not as root. As this is about deleting files, I won't take responsibility if it deletes something wrong.

mxmlnkn avatar Jan 13 '18 04:01 mxmlnkn

I've just written a version based on @mxmlnkn's code, which uses the time data in the relevant trashinfo file instead. In addition, this uses the time as well as the date, so trash-empty 1 will be exactly 24 hours, instead of rounding off to the day. It also trashes from the "normal" directory as well, so it should be a drop-in replacement for the version in this repository. Thank you for the script @mxmlnkn, this is essentially a heavily modified version of your original one.

I had a look at the original code from this repository, thinking that I might be able to modify it, but unfortunately my python is too weak. Presumably it's just adding a scan for all mountpoints though? Otherwise, feel free to use/adapt this code (in the meantime?).

#!/usr/bin/env sh
# This script iterates through likely trash directories, and trashes files
# older than the number of days specified by the optional argument.

# Define usage
usage() {
  cat <<EOF
Usage: $0 [-d|-h] [days]
  -d          dry run
  -h          display this help text and exit
EOF
  exit 1
}

# Parse options
dry='false'
while getopts 'dh' opt; do
  case "${opt}" in
    d) dry='true' ;;
    *) usage; exit 1 ;;
  esac
done
shift $((OPTIND-1))

# Act on dot files too
shopt -s dotglob
# Don't use a literal * if the directory is empty
shopt -s nullglob

# Get current date and time, and convert to epoch time
cursecs=$(date +%s)
maxdays=$1
maxsecs=$((maxdays * 86400)) # 86400 seconds in a day

# Check and delete files in a directory, given as an argument
analyse_trashdir() {
  trashdir="$1"
  echo "Inspecting $trashdir/ ..."
  # Iterate through info directory. If there are files without an info, they will be missed
  for file in $trashdir/info/*; do
    # Get date of deletion from the trashinfo file
    deldate=$(sed -n 's/^DeletionDate=\(.*\)/\1/p' "$file")
    # Convert date to epoch time
    delsecs=$(date -d $deldate +%s)
    diffsecs=$((cursecs - delsecs))
    if [ $diffsecs -gt $maxsecs ]; then
      basefile=$(basename "$file" .trashinfo)
      echo "  Deleting $basefile"
      # Command to delete the file itself
      delfile="rm -rf \"$(dirname "$(dirname "$file")")/files/$basefile\""
      # Command to delete the info too
      delinfo="rm -rf \"${file}\""
      # Indicate and delete the actual files. Separate the file and info, so error messages make sense.
      echo "    $delfile"
      if ! $dry; then
        eval "$delfile"
      fi
      echo "    $delinfo"
      if ! $dry; then
        eval "$delinfo"
      fi
    fi
  done
}

# Analyse trash directories based on mountpoints. Ignore those that will likely not contain trashes
for mountpoint in $(</proc/mounts cut -d ' ' -f2 | grep '^/\(boot\|dev\|proc\|run\|sys\|tmp\)' -v); do
  for trash_reldir in ".Trash/$UID" ".Trash-$UID"; do
    if [ -d "$mountpoint/$trash_reldir" ]; then
      analyse_trashdir "$mountpoint/$trash_reldir"
    fi
  done
done

# Analyse the normal location
if [ -d "$HOME/.local/share/Trash" ]; then
  analyse_trashdir "$HOME/.local/share/Trash"
fi

# Maybe look in $XDG_DATA_HOME/Trash too? But this might be $HOME/.local/share/Trash

protist avatar Apr 19 '18 10:04 protist

Might have been an installation problem... I use eCrypt fs which comes with ubuntu for home directory encryption. I installed but it wouldn't work out of the box without setting up some new trash folders around. Which is odd since it could see Nautilus trash, but it wouldn't use it so I made ~/.Trash-1000/ and a root one. The errors could be a little more useful

FossPrime avatar Oct 16 '20 20:10 FossPrime

Hi, I am having the exact same problem. I have several partitions, trash-put works to the corresponding trash partition but trash-list and trash-empty don't. Is this issue going to be solved? Thanks for your time.

yoarch avatar Oct 28 '20 11:10 yoarch

I may run into the same issue with btrfs. I have my btrfs partition mounted at ~, with a btrfs subvolume ~/storage inside it. Technically they are not the same filesystem (reporting different device id), but they are not shown in /proc/mounts since there is only one mount point ~.

When I use trash-put on a file under ~/storage, it will be moved to ~/storage/.Trash-1000 because we cannot move across subvolume (different filesystem). And for trash-list or trash-empty, this trash directory is ignored and only ~/.local/share/Trash is considered.

In this case, @mxmlnkn 's script https://github.com/andreafrancia/trash-cli/issues/56#issuecomment-357408114 also doesn't help. It's not easy to enumerate all btrfs subvolume since btrfs subvolume list requires root permission and read-only snapshots are also counted as subvolumes.

oxalica avatar Aug 27 '21 18:08 oxalica