Hvordan sletter man alle hardlinkede filer i en bestemt mappe? [LØST]
Når jeg laver backup med rsync bruger jeg parametren --link-dest som opretter hardlinks til filer som allerede findes i destinationen. Derved opnår man at have en række backups som hver især er at betragte som en fuld backup uden dog at tage andet plads op end de nye og ændrede filer. Det fungerer rigtigt godt.
Nu vil jeg dog rydde op i min backup og er stødt på et problem!
Jeg har måske 10-12 forskellige udgaver af en mappestruktur hvor som sagt de ens filer blot er hardlinkede. Så når jeg sletter filer og mapper jeg ikke skal bruge, så forsvinder de slet ikke, tælleren formindskes bare med en. Først når ikke flere hardlinks peger på filerne, forsvinder de.
Dette er jo helt efter bogen. Spørgsmålet er nu hvordan jeg på en snild måde kan slette alle filerne sådan at de ryger væk på tværs af hardlinks!
Jeg kender godt til inodes og -samefile optionen til find, men jeg har hundredevis af disse filer så det vil være en gevaldig opgave at jagte dem manuelt en for en.
I stedet må det være muligt at lave en kommando/script som virker således:
1. Find alle hardlinkede filer i en vis mappestruktur
2a. For alle fundne filer, find og slet alle hardlinkede udgaver, eller
2b. Slet den pågældende inode direkte hvis det er muligt
Nogen hints til en sådan kommando?
Nu vil jeg dog rydde op i min backup og er stødt på et problem!
Jeg har måske 10-12 forskellige udgaver af en mappestruktur hvor som sagt de ens filer blot er hardlinkede. Så når jeg sletter filer og mapper jeg ikke skal bruge, så forsvinder de slet ikke, tælleren formindskes bare med en. Først når ikke flere hardlinks peger på filerne, forsvinder de.
Dette er jo helt efter bogen. Spørgsmålet er nu hvordan jeg på en snild måde kan slette alle filerne sådan at de ryger væk på tværs af hardlinks!
Jeg kender godt til inodes og -samefile optionen til find, men jeg har hundredevis af disse filer så det vil være en gevaldig opgave at jagte dem manuelt en for en.
I stedet må det være muligt at lave en kommando/script som virker således:
1. Find alle hardlinkede filer i en vis mappestruktur
2a. For alle fundne filer, find og slet alle hardlinkede udgaver, eller
2b. Slet den pågældende inode direkte hvis det er muligt
Nogen hints til en sådan kommando?
Kommentarer5
Forstår jeg dig ret hvis
http://www.cyberciti.biz/tips/delete-remove-files-with-inode-number.html
Hvor det lader til du kan bruge kommandoen:
find . -inum [inode-number] -exec rm -i {} \;
Du forstår mig sådan set
Jeg kender godt den pågældende kommando, men jeg har hundredevis af filer som hver især har en del hardlinks. Så skal jeg med andre ord udføre kommandoen nogle hundrede gange, og det orker jeg lissom ikke!
Det jeg er på udkig efter er et script eller en kommando som gør det samme for alle hardlinkede filer i en specifik mappe.
Jeg har så i mellemtiden tænkt over en anden algoritme end nævnt i #0 som er mere effektiv:
1. Brug find kommandoen + fx awk til at lave en oversigt over alle hardlinkede filer i mappen, eller evt. på hele partitionen; der skal kun bruges inode + fuld sti til filerne.
2. Med udgangspunkt i den genererede fil skal der så slettes alle filer der delere inode med filerne i en bestemt mappe.
Fordelen her er at mapperne ikke skal gennemløbes en masse gang.
Du kunne gøre noget i stil
#Lav en liste over filer med deres inodes
find /sti/til/backup -type f -exec ls -i '{}' \; > file_list
#Lave en liste over de inode numre du vil af med antager af dir_to_delete er navnet på en undermappe til backup-stien
$inode_list = $(grep "dir_to_delete" file_list | cut -d" " -f1 | sort -u);
for inode in $inode_list; do
for file in $( cat file_list | grep "^$inode" | cut -d" " -f2 ); do
rm -v "$file"
done
done
Jeg tager intet ansvar for om det virker :) Jeg forudser dog nogle problemer med mellemrum i filnavne.
Det ser umiddelbart godt ud
Det virker! Jeg skulle kun
#!/bin/bash
dir_to_delete="/7kjbxus1.default.bak";
inode_list=$(grep "$dir_to_delete" file_list | cut -d" " -f1 | sort -u)
for inode in $inode_list; do
for file in $( cat file_list | grep "^$inode" | cut -d" " -f2 ); do
#rm -v $file
echo $file
done
done
Læg mærke til at jeg har skrevet echo i stedet for rm. Det gør jeg altid mens jeg tester scripts for at undgå ulykker :-)
Eneste der mangler er at den også sletter de tomme mapper. De bliver ladt tilbage nu. Det skyldes jo -type f som derved kun finder filerne og ikke mapperne.
Enten kan man køre hele herligheden to gange hvor man først går efter filer og så mapperne (hvis man gør det i samme kørsel går der måske ged i det fordi man sletter mapper før filer). Eller man kan evt slette tomme mapper med:
find . -depth -type d -empty -delete
1000 tak :)