trash-cli
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.
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!
I'm seeing the same issue. It seems that trash-empty only operates on ~/.local/share/Trash.
@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?
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
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.
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
Same:
trash-empty/trash-listnever works inside other partitions for me, it doesn't matter which filesystem, I've tried both ext4 and ntfs. I hadrmas an alias totrash-putbut in truth it's quite annoying, because anytime I do arm(trash-putin fact) on a file in whatever partition I have, the files get moved to a/.Trash-1000directory at the partition that file resides, buttrash-empty/trash-listjust recognizes the trash of my system's partition, not the others, so I can't forget to delete those/.Trash-1000directories with/bin/rm.
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 But this doesn't look like it takes the trash-empty argument for the number of days. (See man trash-empty.)
@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.
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
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
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.
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.