-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcleanupdate
executable file
·1442 lines (1409 loc) · 49.4 KB
/
cleanupdate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#
# 'cleanupdate' by cubanpit at github.com
#
# Initial script found somewhere on internet (thanks to unknown).
# Menu taken from a script by Chrysostomus.
#
# This script should help you to maintain an ArchLinux-based system.
# Report issues at github.com/cubanpit/cleanupdate
#
################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
# -e: Exit immediately if a command exits with a non-zero status.
# -u: Treat unset variables as an error when substituting.
# -o pipefail: Pipe redirection raise an error if any command raise one.
set -e -u -o pipefail
# Default language is English, but Italian it's available
_LNG="eng"
if [[ "$LANG" =~ "it_IT" ]]; then
_LNG="ita"
fi
# This script should not be executed as root.
if [[ "$(id -u)" = "0" ]]; then
echo "This script should not be executed as root." 1>&2
echo "Please retry running it as user." 1>&2
exit 126
fi
# Check if tput is installed, otherwise some commands can't work
if [[ ! $(command -v tput) ]]; then
if [[ $_LNG = ita ]]; then
echo "ERRORE: tput non è presente sul sistema, verificare che la"\
"libreria 'ncurses' sia installata correttamente." 1>&2
else
echo "ERROR: tput is not present in the system, verify that"\
"verify that 'ncurses' library is properly installed." 1>&2
fi
exit 1
fi
# Define some useful text style and color
_BOLD=$(tput bold)
_NORMAL=$(tput sgr0)
_RED=$(tput setaf 1)
_GREEN=$(tput setaf 2)
_YELLOW=$(tput setaf 3)
_AQUA=$(tput setaf 6)
readonly _BOLD _NORMAL _RED _GREEN _YELLOW _AQUA
# Define TTY, in order to tell if we are on TTY or PTS
TTY=$(tty)
export TTY
# check if env variable is set in the right way
# https://stackoverflow.com/questions/3601515
if [ -z ${CU_PKEXEC+x} ]; then
CU_PKEXEC="false"
fi
# Choose 'sudo' or 'pkexec' based on env variables
if [[ ! $(command -v pkexec) || ! $(command -v pkttyagent) || "$CU_PKEXEC" != true ]]; then
_SUDO="sudo"
else
_SUDO="pkexec"
# start pkttyagent for this shell, so pkexec is able to ask for authentication
_SHPID=$BASHPID
pkttyagent -p "$_SHPID" --fallback &
unset _SHPID
_PKPID=$!
readonly _SHPID
fi
readonly _SUDO
# Check if $HOME is defined, otherwise many commands can't work
if [[ -z $HOME ]]; then
if [[ $_LNG = ita ]]; then
echo "ERRORE: la variabile d'ambiente $HOME è vuota,"\
"è impossibile ottenere il percorso per la home dell'utente." 1>&2
else
echo "ERROR: $HOME variable not set properly,"\
"it is impossible to get the path of user's home." 1>&2
fi
exit 1
fi
#
# Function that prints warning message and wait for user input when the script
# terminates unexpectedly.
#
function exit_trap {
if [[ "$_SUDO" = pkexec ]]; then
# Kill pkttyagent process
kill "$_PKPID"
fi
echo 1>&2
echo 1>&2
if [[ $_LNG = ita ]]; then
echo "Lo script è terminato in modo non previsto. È possibile"\
"rileggere alcuni messaggi di errore nel file '/tmp/cleanupdate.log'"\
"fino al prossimo riavvio." 1>&2
echo "Premere un tasto qualsiasi per uscire." 1>&2
else
echo "Script terminated unexpectedly. It is possible to read some error"\
"messages also in '/tmp/cleanupdate.log' until the next reboot."\
1>&2
echo "Press any key to exit." 1>&2
fi
read -rs -n1
}
# Define trap for any type of EXIT, calls the previous defined function
trap exit_trap EXIT
# Define little function to print errors in stderr and in a logfile
function print_errors {
tee --append "$logfile" 1>&2
}
#
# Function to convert file size in a format easier to read, it receives file
# size in bytes.
# Usage: human_size "size in bytes"
#
function human_size {
local num=$1
if [[ $num -ge 1000000000 ]]; then
num="$(( num / 1000000000 )) GB"
elif [[ $num -ge 1000000 ]]; then
num="$(( num / 1000000 )) MB"
elif [[ $num -ge 1000 ]]; then
num="$(( num / 1000 )) kB"
elif [[ $num -ge 0 ]]; then
num="$num B"
else
if [[ $_LNG = ita ]]; then
echo "ERRORE: impossibile convertire numeri negativi." | \
print_errors
else
echo "ERROR: it's not possible to convert negative numbers." | \
print_errors
fi
exit 1
fi
echo "$num"
}
#
# Function to print a message after a transaction, communicating if it has been
# executed, has been cenceled or has been skipped because unuseful.
# Usage: end_msg "ok|no|skip|warn" "message"
function end_msg {
local mod=$1
local msg=$2
if [[ $mod = ok ]]; then
if [[ $_LNG = ita ]]; then
echo "${_BOLD}[${_GREEN}ESEGUITO${_NORMAL}"\
"${_BOLD}] $msg ${_NORMAL}"
else
echo "${_BOLD}[${_GREEN}DONE${_NORMAL}${_BOLD}]"\
"$msg ${_NORMAL}"
fi
elif [[ $mod = no ]]; then
if [[ $_LNG = ita ]]; then
echo "${_BOLD}[${_RED}ANNULLATO${_NORMAL}${_BOLD}]"\
"$msg ${_NORMAL}"
else
echo "${_BOLD}[${_RED}CANCELED${_NORMAL}${_BOLD}]"\
"$msg ${_NORMAL}"
fi
elif [[ $mod = skip ]]; then
if [[ $_LNG = ita ]]; then
echo "${_BOLD}[${_AQUA}SALTATO${_NORMAL}${_BOLD}]"\
"$msg ${_NORMAL}"
else
echo "${_BOLD}[${_AQUA}SKIPPED${_NORMAL}${_BOLD}]"\
"$msg ${_NORMAL}"
fi
elif [[ $mod = warn ]]; then
if [[ $_LNG = ita ]]; then
echo "${_BOLD}[${_YELLOW}ATTENZIONE${_NORMAL}"\
"${_BOLD}] $msg ${_NORMAL}"
else
echo "${_BOLD}[${_YELLOW}WARNING${_NORMAL}"\
"${_BOLD}] $msg ${_NORMAL}"
fi
else
if [[ $_LNG = ita ]]; then
echo "ERRORE: modalità sconosciuta, vedere funzione end_msg()." | \
print_errors
else
echo "ERROR: unknown option, see end_msg() function." | print_errors
fi
exit 1
fi
}
#
# Function to print a question, setting the default answer.
# Returns 0 for positive answer, 1 for negative answer.
# Usage: qst_msg "yes|no" "question" && answer=yes || answer=no
#
function qst_msg {
local mod=$1
local msg=$2
# Empty stdin buffer, this way the distract user can not answer to every
# question just pressing enter N times when the script begins.
local discard
set +e
# shellcheck disable=SC2034
read -r -t 0.1 -n 1000 discard
set -e
unset discard
if [[ $mod = yes ]]; then
if [[ $_LNG = ita ]]; then
echo -n "${_BOLD}${_YELLOW}>>${_NORMAL}${_BOLD}"\
"$msg [S/n]?${_NORMAL} "
else
echo -n "${_BOLD}${_YELLOW}>>${_NORMAL}${_BOLD}"\
"$msg [Y/n]?${_NORMAL} "
fi
read -r sure
if [[ $sure = n || $sure = N ]]; then
return 1
else
return 0
fi
elif [[ $mod = no ]]; then
if [[ $_LNG = ita ]]; then
echo -n "${_BOLD}${_YELLOW}>>${_NORMAL}${_BOLD}"\
"$msg [s/N]?${_NORMAL} "
read -r sure
if [[ $sure = s || $sure = S ]]; then
return 0
else
return 1
fi
else
echo -n "${_BOLD}${_YELLOW}>>${_NORMAL}${_BOLD}"\
"$msg [y/N]?${_NORMAL} "
read -r sure
if [[ $sure = y || $sure = Y ]]; then
return 0
else
return 1
fi
fi
else
if [[ $_LNG = ita ]]; then
echo "ERRORE: risposta predefinita sconosciuta, vedere funzione"\
"qst_msg()." | print_errors
else
echo "ERROR: unknown default answer, see qst_msg() function." | \
print_errors
fi
exit 1
fi
}
#
# Function to check arguments passed to the script.
# This script doesn't accept any argument.
#
function check_args {
if [[ $# -gt 0 ]] ; then
if [[ $_LNG = ita ]]; then
echo "Errore! Sono stati forniti i seguenti argomenti:" | \
print_errors
else
echo "Error! Some arguments have been provided:" | print_errors
fi
echo -en "\\t" | print_errors ; for i in "$@" ; \
do echo -n "$i" | print_errors ; echo -n " " | print_errors ; done ; \
echo | print_errors ; echo | print_errors
if [[ $_LNG = ita ]]; then
echo "Cleanupdate non ha bisogno di alcun argomento. Per maggiori"\
"informazioni leggere il manuale cleanupdate(7)." | print_errors
else
echo "Cleanupdate doesn't need any argument. For further"\
"information read the manual page cleanupdate(7)."| print_errors
fi
exit 1
fi
}
#
# This function checks if there is any orphan package and asks the user if he
# wants to remove them.
#
function orph_pkgs {
echo -e "\\nStart orph_pkgs()\\n" >> "$logfile"
echo
function end_orph {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Pacchetti orfani"
else
end_msg "$1" "Orphan packages"
fi
}
if [[ $_LNG = ita ]]; then
echo "Ricerca pacchetti orfani in corso..."
else
echo "Looking for orphan packages..."
fi
local -a orphans=""
if pacman -Qdtq >/dev/null ; then
readarray -t orphans < <( pacman -Qdtq )
fi
if [[ -n ${orphans[0]} ]]; then
if [[ $_LNG = ita ]]; then
end_msg "warn" "Sono presenti pacchetti orfani, se non sono stati installati volontariamente ne è consigliata la rimozione."
else
end_msg "warn" "There are orphan packages, if you haven't installed them explicitly it's a good choice to remove them."
fi
for i in "${orphans[@]}"; do
echo "$i"
done | column -x
if [[ $_LNG = ita ]]; then
qst_msg "no" "Sono presenti ${#orphans[@]} pacchetti orfani, desideri rimuoverli" && sure=yes || sure=no
else
qst_msg "no" "There are ${#orphans[@]} orphaned packages, do you want to remove them" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
if $_SUDO pacman --color always --noconfirm -Rs \
"${orphans[@]}" 2> >(print_errors); then
end_orph "ok"
else
end_orph "no"
fi
else
end_orph "no"
fi
echo
else
if [[ $_LNG = ita ]]; then
echo "Non sono presenti pacchetti orfani."
end_orph "skip"
else
echo "There are no orphan packages."
end_orph "skip"
fi
echo
fi
}
#
# Function containing all system update operation.
# Database sync, package upgrade, AUR upgrade.
#
function sys_update {
echo -e "\\nStart sys_update()\\n" >> "$logfile"
if [[ $_LNG = ita ]]; then
echo " ${_BOLD}::Aggiornamento del sistema::${_NORMAL} "
else
echo " ${_BOLD}::System update::${_NORMAL} "
fi
echo
function end_sysup {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Aggiornamento pacchetti ufficiali"
else
end_msg "$1" "Official packages upgrade"
fi
}
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Desideri aggiornare i pacchetti ufficiali" && sure=yes || sure=no
else
qst_msg "yes" "Do you want to upgrade official packages" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
# compute age of mirrorlist in days from last modification
local ml_age=$(( ($(date +%s) - \
$(stat --format %Y /etc/pacman.d/mirrorlist)) / 86400 ))
if [[ $(command -v pacman-mirrors) && $ml_age -gt 0 ]]; then
if [[ $_LNG = ita ]]; then
qst_msg "yes" "La lista dei mirror non viene aggiornata da $ml_age giorno(i), desideri aggiornarla" && sure=yes || sure=no
else
qst_msg "yes" "The mirror list is $ml_age day(s) old, do you want to refresh it" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
if ! $_SUDO pacman-mirrors --fasttrack 10 2> >(print_errors) ; then
if [[ $_LNG = ita ]]; then
end_msg "no" "Aggiornamento mirrorlist"
else
end_msg "no" "Mirrorlist refresh"
fi
fi
if ! $_SUDO pacman -Syy 2> >(print_errors); then
if [[ $_LNG = ita ]]; then
end_msg "warn" "La lista dei mirror è stata aggiornata, si raccomanda un aggiornamento manuale dei database locali di pacman."
else
end_msg "warn" "Mirrorlist refreshed, it is reccomended to manual refresh pacman local databases."
fi
exit 1
fi
else
if ! $_SUDO pacman -Sy 2> >(print_errors); then
if [[ $_LNG = ita ]]; then
end_msg "no" "Aggiornamento database locali"
else
end_msg "no" "Local database refresh"
fi
fi
fi
else
if ! $_SUDO pacman -Sy 2> >(print_errors); then
if [[ $_LNG = ita ]]; then
end_msg "no" "Aggiornamento database locali"
else
end_msg "no" "Local database refresh"
fi
fi
fi
if [[ $_LNG = ita ]]; then
echo "Ricerca aggiornamenti in corso..."
else
echo "Looking for updates..."
fi
if [[ -n $(pacman -Qu 2> /dev/null) ]]; then
# This way any pacman error during update doesn't stop the script
if $_SUDO pacman -Su --color always 2> >(print_errors); then
end_sysup "ok"
else
end_sysup "no"
fi
else
if [[ $_LNG = ita ]]; then
echo "Non sono disponibili nuovi aggiornamenti."
end_sysup "skip"
else
echo "There isn't any available update."
end_sysup "skip"
fi
fi
else
end_sysup "no"
fi
echo
function end_aurup {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Aggiornamento AUR"
else
end_msg "$1" "AUR upgrade"
fi
}
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Desideri aggiornare i pacchetti di AUR" && sure=yes || sure=no
else
qst_msg "yes" "Do you want to upgrade AUR packages" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
orph_pkgs
# Check if yay, trizen or pamac are installed
if [[ $(command -v yay) ]]; then
if yay -Sua 2> >(print_errors) ; then
end_aurup "ok"
else
end_aurup "no"
fi
elif [[ $(command -v trizen) ]]; then
if trizen -Sua 2> >(print_errors) ; then
end_aurup "ok"
else
end_aurup "no"
fi
elif [[ $(command -v pamac) ]]; then
if [[ $_LNG = ita ]]; then
echo "Verrà utilizzato Pamac per eseguire l'aggiornamento dei"\
"pacchetti di AUR, date le caratteristiche di questo strumento"\
"verrà anche avviato l'aggiornamento dei pacchetti ufficiali."
else
echo "Pamac is used to upgrade AUR packages, because of the"\
"tool's characteristics an upgrade of official packages will"\
"also be triggered."
fi
if pamac update --aur 2> >(print_errors) ; then
end_aurup "ok"
else
end_aurup "no"
fi
else
if [[ $_LNG = ita ]]; then
echo "Non risulta installato 'yay', 'trizen' né 'pamac', non è"\
"possibile accedere agli aggiornamenti AUR tramite questo"\
"script."
end_aurup "skip"
else
echo "You don't have 'yay', 'trizen' or 'pamac' installed,"\
"you can't access AUR updates through this script."
end_aurup "skip"
fi
fi
else
end_aurup "no"
fi
}
#
# Function containing all package cleaning operation.
# Orphaned packages cleaning, cache cleaning, database optimization.
#
function clean_pkg {
echo -e "\\nStart clean_pkg()\\n" >> "$logfile"
if [[ $_LNG = ita ]]; then
echo " ${_BOLD}::Pulizia pacchetti::${_NORMAL} "
else
echo " ${_BOLD}::Packages cleaning::${_NORMAL} "
fi
orph_pkgs
if [[ $_LNG = ita ]]; then
echo "Controllo cache dei pacchetti installati in corso..."
else
echo "Checking installed package cache..."
fi
function end_pacc {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Pulizia cache pacchetti installati"
else
end_msg "$1" "Installed packages cache cleaning"
fi
}
if paccache -dk2 | grep -q "no candidate packages found for pruning"; then
if [[ $_LNG = ita ]]; then
echo "Pulizia cache non necessaria."
end_pacc "skip"
else
echo "Cache cleaning not required."
end_pacc "skip"
fi
else
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Desideri pulire la cache dei pacchetti installati (conservando le ultime 2 versioni)" && sure=yes || sure=no
else
qst_msg "yes" "Do you want to clean the cache of installed packages (keeping 2 versions)" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
if $_SUDO paccache -rk2 --nocolor 2> >(print_errors); then
end_pacc "ok"
else
end_pacc "no"
fi
else
end_pacc "no"
fi
fi
echo
if [[ $_LNG = ita ]]; then
echo "Controllo cache dei pacchetti disinstallati in corso..."
else
echo "Checking uninstalled package cache..."
fi
function end_pacc {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Pulizia cache pacchetti disinstallati"
else
end_msg "$1" "Uninstalled packages cache cleaning"
fi
}
if paccache -duk0 | grep -q "no candidate packages found for pruning"; then
if [[ $_LNG = ita ]]; then
echo "Pulizia cache non necessaria."
end_pacc "skip"
else
echo "Cache cleaning not required."
end_pacc "skip"
fi
else
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Desideri pulire completamente la cache dei pacchetti disinstallati" && sure=yes || sure=no
else
qst_msg "yes" "Do you want to completely clean the cache of uninstalled packages" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
if $_SUDO paccache -ruk0 --nocolor 2> >(print_errors); then
end_pacc "ok"
else
end_pacc "no"
fi
else
end_pacc "no"
fi
fi
echo
# Here we'll check for '.pacnew' files, then catch '.pacnew' files that are
# useless (there is 'foo.conf.pacnew' and not 'foo.conf'), finally warn the
# user about it.
# Temporarely disable pipefail option, find often reports non critical errors.
set +o pipefail
local i=0
local -a pacnews=""
while IFS= read -r -d '' file; do
pacnews[i++]="$file"
done < <(find /etc -name "*.pacnew" -print0 2>>"$logfile")
set -o pipefail
local -a orphan_pacnews=""
if [[ -n ${pacnews[0]} ]]; then
local -i j=0
for i in "${pacnews[@]}"; do
local pacold=${i//\.pacnew/}
if [[ ! -f "$pacold" ]]; then
orphan_pacnews[j++]="$pacold.pacnew"
fi
done
fi
if [[ -n ${orphan_pacnews[0]} ]]; then
echo
for i in "${orphan_pacnews[@]}"; do
echo "$i"
done
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Sono presenti questi ${#orphan_pacnews[@]} file '.pacnew' orfani (consultare la documentazione [8] per maggiori informazioni), vuoi eliminarli" && sure=yes || sure=no
else
qst_msg "yes" "These are ${#orphan_pacnews[@]} orphan '.pacnew' files (read documentation [8] for further information), do you want to erase them" && sure=yes || sure=no
fi
function end_pnew {
if [[ $_LNG = ita ]]; then
end_msg "$1" "File di configurazione orfani"
else
end_msg "$1" "Orphan configuration files"
fi
}
if [[ $sure != no ]]; then
# shellcheck disable=SC2068
if $_SUDO rm -f ${orphan_pacnews[@]} 2> >(print_errors); then
end_pnew "ok"
else
end_pnew "no"
fi
else
end_pnew "no"
fi
fi
if [[ -n ${pacnews[0]} && ( ${#pacnews[@]} -gt ${#orphan_pacnews[@]} || -z ${orphan_pacnews[0]} ) ]]; then
echo
if [[ $_LNG = ita ]]; then
end_msg "warn" "Sono presenti nuove versioni di alcuni file di configurazione. Valutare le modifiche tramite il comando 'pacdiff'. Consultare la documentazione [8] per maggiori informazioni."
else
end_msg "warn" "There are updated version of some configuration files. Assess the changes with the command 'pacdiff'. Read documentation [8] for further information."
fi
fi
}
#
# Function containing all file cleaning operation.
# Cache & thumbs cleaning, residual file cleaning, trash cleaning.
#
function clean_file {
echo -e "\\nStart clean_file()\\n" >> "$logfile"
if [[ $_LNG = ita ]]; then
echo " ${_BOLD}::Pulizia file::${_NORMAL} "
else
echo " ${_BOLD}::Files cleaning::${_NORMAL} "
fi
if [[ "$(cat /proc/1/comm)" = systemd ]]; then
echo
function end_journal {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Pulizia file di log"
else
end_msg "$1" "Log files cleaning"
fi
}
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Desideri controllare la dimensione del journal log" && sure=yes || sure=no
else
qst_msg "yes" "Do you want to check journal log disk usage" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
if [[ $_LNG = ita ]]; then
echo "Controllo della dimensione del journal log in corso..."
else
echo "Checking journal log disk usage..."
fi
# Check journal log files, consider realistic cases only order of MB and GB.
local log_size
local -a size_arr
# Assign variable without spawning subshell using a FIFO
# https://stackoverflow.com/questions/21632126
mkfifo /tmp/cu_fifo; exec 3<> /tmp/cu_fifo; unlink /tmp/cu_fifo
$_SUDO journalctl --disk-usage 2>>"$logfile" | sed -e "s/[a-z]//g" | \
sed -e "s/\\s\\+/ /g" | cut -d" " -f 2 >&3
read -r -u3 size_arr
exec 3>&-
log_size=${size_arr[0]}
if echo "$log_size" | grep -q G ; then
log_size=$(echo "1000*${log_size/[A-Z]/}" | bc)
else
log_size=${log_size/[A-Z]/}
fi
log_size=${log_size/\.*/}
if [[ $log_size -ge 200 ]]; then
if [[ $_LNG = ita ]]; then
qst_msg "yes" "Potrebbe essere utile restringere il journal log, vuoi procedere" && sure=yes || sure=no
else
qst_msg "yes" "It may be useful to trim journal log, do you want to continue" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
if $_SUDO journalctl --vacuum-size=200M \
--vacuum-time=2weeks | tail -n 1 2> >(print_errors); then
end_journal "ok"
else
end_journal "no"
fi
else
end_journal "no"
fi
else
if [[ $_LNG = ita ]]; then
echo "I file di log non occupano eccessivo spazio su disco."
end_journal "skip"
else
echo "Log files do not use significant disk space."
end_journal "skip"
fi
fi
else
end_journal "no"
fi
fi
echo
if [[ $_LNG = ita ]]; then
echo "Controllo dei log obsoleti in corso..."
else
echo "Checking obsolete log files..."
fi
function end_log {
if [[ $_LNG = ita ]]; then
end_msg "$1" "Pulizia file di log obsoleti"
else
end_msg "$1" "Obsolete log files cleaning"
fi
}
# Check classic log files, they are considered a thousand time heavier
# because they are also obsolete if older than 90 days.
# Temporarely disable pipefail option, find often reports non critical errors.
set +o pipefail
local i=0
local -a obsoletelogs=""
while IFS= read -r -d '' file; do
obsoletelogs[i++]="$file"
done < <(find /var/log -name journal -prune -o \( -type f -ctime +90 \
-print0 \) 2>>"$logfile")
set -o pipefail
if [[ -n ${obsoletelogs[0]} ]]; then
# Print every obsolete log file
for i in "${obsoletelogs[@]}"; do
echo "$i"
done | column -x
if [[ $_LNG = ita ]]; then
qst_msg "no" "Ci sono ${#obsoletelogs[@]} file di log obsoleti, desideri rimuoverli" && sure=yes || sure=no
else
qst_msg "no" "There are ${#obsoletelogs[@]} obsolete log files, do you want to remove them" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
# Remove every residual file
# shellcheck disable=SC2068
if $_SUDO rm -f ${obsoletelogs[@]} 2> >(print_errors); then
end_log "ok"
else
end_log "no"
fi
else
end_log "no"
fi
else
if [[ $_LNG = ita ]]; then
echo "Non sono presenti file di log obsoleti."
end_log "skip"
else
echo "There are no obsolete log files."
end_log "skip"
fi
fi
echo
if [[ $_LNG = ita ]]; then
echo "Stima dello spazio occupato da cache e miniature poco recenti in"\
"corso..."
else
echo "Calculating disk space taken by old cache and thumbnails..."
fi
# This part checks the existence of thumbnails and cache folders, then
# calculate the total space they take.
# Disable pipefail option, because 'find' often exits with errors,
# but these are not critical.
set +o pipefail
local oldsize=0
if [[ -d "$HOME/.thumbnails" ]]; then
# shellcheck disable=SC2216
oldsize=$(echo "$oldsize+$( find "$HOME/.thumbnails" -type f\
-atime +30 -print0 2>>"$logfile" | du --files0-from=- -cb |\
tail -1 | cut -f 1 )" | bc)
# shellcheck disable=SC2216
oldsize=$(echo "$oldsize+$( find "$HOME/.thumbnails" -empty -type d\
-atime +30 -print0 2>>"$logfile" | du --files0-from=- -cb |\
tail -1 | cut -f 1 )" | bc)
fi
if [[ -d "$HOME/.cache" ]]; then
# shellcheck disable=SC2216
oldsize=$(echo "$oldsize+$( find "$HOME/.cache" -type f -atime +30 -print0 \
2>>"$logfile" | du --files0-from=- -cb | tail -1 | cut -f 1 )" | bc)
# shellcheck disable=SC2216
oldsize=$(echo "$oldsize+$( find "$HOME/.cache" -empty -type d -atime +30 \
-print0 2>>"$logfile" | du --files0-from=- -cb | tail -1 | cut -f 1 )" \
| bc)
fi
set -o pipefail
if [[ $oldsize -gt 0 ]]; then
oldsize=$(human_size "$oldsize")
if [[ $_LNG = ita ]]; then
qst_msg "yes" "L'eliminazione di questi file libererà $oldsize di spazio su disco, vuoi procedere" && sure=yes || sure=no
else
qst_msg "yes" "The deletion of these files frees $oldsize of disk space, do you want to continue" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
# Disable pipefail option because 'find' often report not critical errors
set +o pipefail
if [[ -d "$HOME/.thumbnails" ]]; then
find "$HOME/.thumbnails" -type f -atime +30 -print0 2>/dev/null |\
xargs -0 rm -f 2> >(print_errors)
find "$HOME/.thumbnails" -empty -type d -atime +30\
-print0 2>/dev/null | xargs -0 rm -rf 2> >(print_errors)
fi
if [[ -d "$HOME/.cache" ]]; then
find "$HOME/.cache" -type f -atime +30 -print0 2>/dev/null | \
xargs -0 rm -f 2> >(print_errors)
find "$HOME/.cache" -empty -type d -atime +30 -print0 2>/dev/null | \
xargs -0 rm -rf 2> >(print_errors)
fi
set -o pipefail
if [[ $_LNG = ita ]]; then
end_msg "ok" "Pulizia cache e miniature"
else
end_msg "ok" "Thumbs and cache cleaning"
fi
else
if [[ $_LNG = ita ]]; then
end_msg "no" "Pulizia cache e miniature"
else
end_msg "no" "Thumbs and cache cleaning"
fi
fi
else
if [[ $_LNG = ita ]]; then
echo "Non c'è necessità di eliminare alcun"\
"file, le cartelle sono sufficientemente pulite."
end_msg "skip" "Pulizia cache e miniature"
else
echo "There is no need to delete any file,"\
"these folders are pretty clean."
end_msg "skip" "Thumbs and cache cleaning"
fi
fi
echo
if [[ $_LNG = ita ]]; then
echo "Ricerca di file residui in corso..."
else
echo "Searching residual file..."
fi
# Null separated output will be used just to have less problem with
# strange characters.
# Bash pipefail option is disabled temporarly, see previous comments.
set +o pipefail
local i=0
local -a residfiles=""
while IFS= read -r -d '' file; do
residfiles[i++]="$file"
done < <(find "$HOME" -name "*Steam*" -prune -o -path\
"$HOME/.cache" -prune -o -path "$HOME/.thumbnails" -prune -o\
-path "$HOME/.mozilla" -prune -o -path "$HOME/.thunderbird" -prune\
-o -path "*/.git" -prune -o \( -type f -atime +1 -name "*~"\
-user "$USER" -print0 \) 2>>"$logfile")
while IFS= read -r -d '' file; do
residfiles[i++]="$file"
done < <(find "$HOME" -name "*Steam*" -prune -o -path\
"$HOME/.cache" -prune -o -path "$HOME/.thumbnails" -prune -o\
-path "$HOME/.mozilla" -prune -o -path "$HOME/.thunderbird" -prune\
-o -path "*/.git" -prune -o \( -type f -atime +1 -name ".*.swp"\
-user "$USER" -print0 \) 2>>"$logfile")
while IFS= read -r -d '' file; do
residfiles[i++]="$file"
done < <(find "$HOME" -name "*Steam*" -prune -o -path\
"$HOME/.cache" -prune -o -path "$HOME/.thumbnails" -prune -o\
-path "$HOME/.mozilla" -prune -o -path "$HOME/.thunderbird" -prune\
-o -path "*/.git" -prune -o -name "Desktop.ini" -user "$USER"\
-print0 2>>"$logfile")
while IFS= read -r -d '' file; do
residfiles[i++]="$file"
done < <(find "$HOME" -name "*Steam*" -prune -o -path\
"$HOME/.cache" -prune -o -path "$HOME/.thumbnails" -prune -o\
-path "$HOME/.mozilla" -prune -o -path "$HOME/.thunderbird" -prune\
-o -path "*/.git" -prune -o -name "Thumbs.db" -user "$USER" -print0\
2>>"$logfile")
set -o pipefail
if [[ -n ${residfiles[0]} ]]; then
# Print every residual file
for i in "${residfiles[@]}"; do
echo "$i"
done | column -x
# Calculate space taken by residual files
local residsize=0
local filesize=0
for i in "${residfiles[@]}"; do
filesize=$( du -b "$i" | cut -f 1 )
residsize=$( echo "$residsize+$filesize" | bc )
done
residsize=$(human_size "$residsize")
if [[ $_LNG = ita ]]; then
qst_msg "no" "Ci sono ${#residfiles[@]} file residui che occupano $residsize di spazio su disco, desideri rimuoverli" && sure=yes || sure=no
else
qst_msg "no" "There are ${#residfiles[@]} residual files that take $residsize of disk space, do you want to remove them" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
# Remove every residual file
for i in "${residfiles[@]}"; do
rm -f "$i" 2> >(print_errors)
done
if [[ $_LNG = ita ]]; then
end_msg "ok" "Pulizia file residui"
else
end_msg "ok" "Residual files cleaning"
fi
else
if [[ $_LNG = ita ]]; then
end_msg "no" "Pulizia file residui"
else
end_msg "no" "Residual files cleaning"
fi
fi
else
if [[ $_LNG = ita ]]; then
echo "Non sono presenti file residui."
end_msg "skip" "Pulizia file residui"
else
echo "There are no residual files."
end_msg "skip" "Residual files cleaning"
fi
fi
echo
if [[ $_LNG = ita ]]; then
echo "Stima dimensioni dei file nel cestino in corso..."
else
echo "Checking trash files size..."
fi
if [[ -d "$HOME/.local/share/Trash/files" ]]; then
# Bash pipefail option is disabled temporarly, see previous comments.
set +o pipefail
local i=0
local -a trashfiles=""
while IFS= read -r -d '' file; do
trashfiles[i++]="$file"
done < <(find "$HOME/.local/share/Trash/files" -mindepth 1\
-maxdepth 1 -print0 2>>"$logfile")
set -o pipefail
local trashsize=0
if [[ -n ${trashfiles[0]} ]]; then
local filename=""
local filesize=0
# This for loop counts total space taken by files and prints every
# file name next to the file size.
for i in "${trashfiles[@]}"; do
filename=$( basename "$i" )
filesize=$( du -bs "$i" | cut -f 1 )
trashsize=$( echo "$trashsize+$filesize" | bc )
filesize=$( human_size "$filesize" )
echo -ne " $filesize \\t"
if [[ -d "$i" ]]; then
filename+="/"
echo "${_BOLD}$filename${_NORMAL}"
else
echo "$filename"
fi
done
trashsize=$(human_size "$trashsize")
if [[ $_LNG = ita ]]; then
qst_msg "no" "Sono presenti ${#trashfiles[@]} elementi che occupano $trashsize di spazio sul disco, desideri eliminarli definitivamente" && sure=yes || sure=no
else
qst_msg "no" "There are ${#trashfiles[@]} items that take $trashsize of disk space, do you want do definetely delete them" && sure=yes || sure=no
fi
if [[ $sure != no ]]; then
rm -rf "$HOME/.local/share/Trash/files" 2> >(print_errors)
rm -rf "$HOME/.local/share/Trash/info" 2> >(print_errors)
if [[ $_LNG = ita ]]; then