You are not logged in.
here is a simple script that I have written which cleans pacman cache folder in a way that only the packages which are now "updated" in the repositories, will get removed. This is different from what "pacman -Sc" does. pacman -Sc also removes any package which is not installed, while this script keeps all the packages which are updated whether they are installed or not.
The functionality is some how like what "apt-get autoclean" does in debian.
to use this script you need to run it with "list" or "clean" arguments. you can also use the "help" argument for more help.
I hope it helps
#! /bin/bash
# clcache - This script cleans pacman cache folder in a way that only the packages
#+ which are now updated in the repositories, will get removed. This is
#+ different from what "pacman -Sc" does. pacman -Sc also removes any package
#+ which is not installed, while this script keeps all the packages which are
#+ updated whether they are installed or not.
# I have tweaked this script to be as fast as possible, it might still need a
#+ couple of minutes to compelete based on the size of your cache folder.
# to use this script you need to run it with "list" or "clean" arguments.
# you can also use the "help" argument for more help.
# This script is written by "Ali Mousavi". Please report bugs to ali.mousavi@gmail.com
DIR="/var/cache/pacman/pkg" #the default directory of pacman cache.
ROOT_UID=0 #Only users with $UID 0 have root privilages.
TMPFILE="/tmp/cache.tmp"
# Run as root
if [ "$UID" -ne "$ROOT_UID" ]
then
echo "Must be root to run this script"
exit 1
fi
# Check for the arguments
if [ -z "$1" ]
then
echo -e 'What should I do?\nValid Argument are "list", "clean" or "help"'
exit 1
elif [ "$1" = "list" ]
then
ACTION="ls"
MESSAGE="Are you sure you want to continue?"
elif [ "$1" = "clean" ]
then
ACTION="rm -vf"
MESSAGE="Are you sure you want to remove outdated packages? This process can not be undone!"
elif [ "$1" = "help" -o "$1" = "-h" -o "$1" = "--help" ]
then
echo -e "This script checks the packages in your pacman cache directory and removes the packages that are outdated. It doesn't matter if the package is installed or not.\n\n3 arguments can be passed to the script:\n\nlist:\n\tchecks for package that are outdated and prints the names.\n\nclean:\n\tremoves outdated packages.\n\nhelp,-h,--help:\n\tprints this help text.\n\nThis script is written by \"Ali Mousavi\". Please report bugs to ali.mousavi@gmail.com"
exit 0
else
echo 'Valid Argument are "list", "clean" or "help"'
exit 1
fi
# Check if the user is sure!
echo "This might take a while based on the amount of cached packages."
echo -n "$MESSAGE(y/n) "
read ANS
if [ $ANS = "y" -o $ANS = "Y" -o $ANS = "yes" ]
then
echo "Processing packages..."
elif [ $ANS = "n" -o $ANS = "N" -o $ANS = "No" ]
then
echo "Exiting on user request"
exit 0
else
echo "Invalid answer"
exit 1
fi
# Process the packages
cd $DIR #change to cache directory.
pacman -Sl | awk '{ print $2" "$3; }' > $TMPFILE
for f in $(ls $DIR)
do
pname=$(file $f | cut -d: -f1) #Produces filename, like: fetchmail-6.3.19-1-i686.pkg.tar.xz"
spname=$(echo $pname | sed 's/-[0-9][0-9]*.*//g') #removes package version: fetchmail
pver=$(echo $pname | sed 's/.*-\([0-9\-\.][0-9\-\.]*-[0-9\-\.][0-9\-\.]*\).*/\1/g') #using pacman -Qi for all files takes a lot of time.
if [ $(echo $pver | grep '[^0-9\-\.\-\-]' | wc -l) != 0 ] #checks if package version is alright
then
pver=$(pacman -Qpi $f | grep Version | awk '{print $3}')
fi
newpver=$(grep -e "^$spname " $TMPFILE | awk '{ print $2 }')
if [[ $newpver != $pver ]]
then
$ACTION $f
fi
done
rm -f $TMPFILE
echo "Outdated packages processed successfully!"
exit 0
Last edited by tuxitop (2011-09-13 09:24:26)
Offline
Good! Thank you very much, I can assume this can be very useful to many users.
Proud Arch Linux user since 2007.
Offline
You posted the question How to remove old packages no matter installed or not from the cache? and I gave you my answer. You never responded.
Your script is at best not free of bugs. Keep learning.
---
For me, the buitin pacman cache cleaning is useful enough. For more sophisticated use cases, the paccache[1] script will most likely serve the purpose.
[1] https://projects.archlinux.org/pacman.g … accache.in
Last edited by lolilolicon (2011-09-13 09:48:35)
This silver ladybug at line 28...
Offline
You posted the question How to remove old packages no matter installed or not from the cache? and I gave you my answer. You never responded.
Well, I'm sorry for that. I think I had forgotten to check "subscribe to this topic". I most have thought that it is checked by default. I didn't know that you have answered to that topic till now.
Your script is at best not free of bugs. Keep learning.
I tried my best to avoid bugs. this script is also a part of my learning process. one of the first scripts I have written. I'll be thankful if you share it's problems with me and I'll probably
Offline
# Check for the arguments if [ -z "$1" ] then echo -e 'What should I do?\nValid Argument are "list", "clean" or "help"' exit 1 elif [ "$1" = "list" ] then ACTION="ls" MESSAGE="Are you sure you want to continue?" elif [ "$1" = "clean" ] then ACTION="rm -vf" MESSAGE="Are you sure you want to remove outdated packages? This process can not be undone!" elif [ "$1" = "help" -o "$1" = "-h" -o "$1" = "--help" ] then echo -e "This script checks the packages in your pacman cache directory and removes the packages that are outdated. It doesn't matter if the package is installed or not.\n\n3 arguments can be passed to the script:\n\nlist:\n\tchecks for package that are outdated and prints the names.\n\nclean:\n\tremoves outdated packages.\n\nhelp,-h,--help:\n\tprints this help text.\n\nThis script is written by \"Ali Mousavi\". Please report bugs to ali.mousavi@gmail.com" exit 0 else echo 'Valid Argument are "list", "clean" or "help"' exit 1 fi
1. `echo -e 'foo\nbar\nbaz'` gets long and unreadable quickly. Instead, use here documents:
cat <<EOF
What should I do?
Valid Argument are "list", "clean" or "help"
EOF
2. Use a case command, looks cleaner:
case "$1" in
'') ... ;;
list) ... ;;
clean) ... ;;
help|-h|--hep) ... ;;
*) ... ;;
# Check if the user is sure! echo "This might take a while based on the amount of cached packages." echo -n "$MESSAGE(y/n) " read ANS if [ $ANS = "y" -o $ANS = "Y" -o $ANS = "yes" ] then echo "Processing packages..." elif [ $ANS = "n" -o $ANS = "N" -o $ANS = "No" ] then echo "Exiting on user request" exit 0 else echo "Invalid answer" exit 1 fi
Try:
read -p "hello: " -r
echo $REPLY
And again, `case` should be cleaner in this case.
# Process the packages cd $DIR #change to cache directory. pacman -Sl | awk '{ print $2" "$3; }' > $TMPFILE
While you quoted a lot, you left these two out. "$DIR" and "$TMPFILE" should be quoted, otherwise whitespaces will break the code.
for f in $(ls $DIR)
Apart from the same missing quotes, calling `ls` is a waste here. The following is sufficient and (maybe surprisingly) more accurate:
for f in *
How is it more accurate? Run this test script:
#!/bin/bash
DIR=/tmp/foo
mkdir -p "$DIR"
cd "$DIR"
touch a\ b c$'\n'd
for i in *; do
printf '+%s+\n' "$i"
done
printf '%s\n' ---
for i in $(ls $DIR); do
printf '+%s+\n' "$i"
done
Let's not go too far here. Just get the idea.
do pname=$(file $f | cut -d: -f1) #Produces filename, like: fetchmail-6.3.19-1-i686.pkg.tar.xz"
Calling `file` here is, again, unnecessary. Also, filename of a package can contain ":", e.g., vi-1:050325-1-i686.pkg.tar.xz, which breaks your code.
Don't complicate things:
pname=$f
spname=$(echo $pname | sed 's/-[0-9][0-9]*.*//g') #removes package version: fetchmail
Broken for ntfs-3g-2011.4.12-1-i686.pkg.tar.xz, nvidia-173xx-utils-173.14.31-1-i686.pkg.tar.xz, etc... Something less lousy:
sed 's/\(-[^-]\+\)\{3\}$//' <<< "$pname"
pver=$(echo $pname | sed 's/.*-\([0-9\-\.][0-9\-\.]*-[0-9\-\.][0-9\-\.]*\).*/\1/g') #using pacman -Qi for all files takes a lot of time.
Although this might work for now, this would break if we had an architecture that starts with a digit, e.g. 686. Something less lousy:
sed 's/\(.*\)-\([^-]\+-[^-]\+\)-[^-]\+$/\2/' <<< "$pname"
if [ $(echo $pver | grep '[^0-9\-\.\-\-]' | wc -l) != 0 ] #checks if package version is alright then pver=$(pacman -Qpi $f | grep Version | awk '{print $3}') fi
Again, calling `wc` here is a waste. Anyway, why is this check necessary at all?
newpver=$(grep -e "^$spname " $TMPFILE | awk '{ print $2 }') if [[ $newpver != $pver ]] then $ACTION $f fi done rm -f $TMPFILE echo "Outdated packages processed successfully!" exit 0
The post is getting too long, so so much from me. If there's anything you don't understand yet, read bash(1).
If I sound harsh or anything, don't be discouraged. Just keep reading, keep improving.
Last edited by lolilolicon (2011-09-13 12:53:04)
This silver ladybug at line 28...
Offline
Wow! thanks for this answer lolilolicon! I wasn't expecting this actually! this is great!
You seem to be very professional at this specially about the regular expressions. I had headache for a couple of hours until I made them and you have read and produced better ones so fast!
I'm working on it and I really appreciate you're comments about my script! it seems that every single line of my script has a problem!
Offline
Heh, it's natural for you to think that way, given that you just started, but I'm far from professional, just a little more experience.
The start is no doubt one of the most exciting stage of learning. Just keep it up, you will catch up soon enough
This silver ladybug at line 28...
Offline