blob: 7803649aa0efa2de0b495d09815e0b095ce1c58b (
plain)
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
|
#!/usr/bin/env bash
# fix-mail-duplicates.sh
# Usage: fix-mail-duplicates.sh /path/to/maildir 682
set -e
# Check if arguments were provided
if [ $# -ne 2 ]; then
echo "Usage: $0 /path/to/maildir UID_NUMBER"
echo "Example: $0 ~/Mail/ben@bensima.com/Archive 682"
exit 1
fi
MAILDIR="$1"
UID_NUM="$2"
# Validate the arguments
if [ ! -d "$MAILDIR" ]; then
echo "Error: Maildir '$MAILDIR' does not exist or is not a directory"
exit 1
fi
if ! [[ "$UID_NUM" =~ ^[0-9]+$ ]]; then
echo "Error: UID must be a number, got '$UID_NUM'"
exit 1
fi
echo "Looking for duplicate UID $UID_NUM in $MAILDIR..."
# Find all files with the EXACT UID (using word boundaries)
DUPLICATE_FILES=$(find "$MAILDIR" -type f -name "*,U=$UID_NUM[,:]*")
FILE_COUNT=$(echo "$DUPLICATE_FILES" | wc -l)
if [ "$FILE_COUNT" -le 1 ]; then
echo "No duplicates found. Nothing to fix."
exit 0
fi
echo "Found $FILE_COUNT files with the same UID $UID_NUM"
# Get timestamps for each file to determine which is newer
declare -A FILE_TIMES
for f in $DUPLICATE_FILES; do
# Get the message Date: header if possible, otherwise use file time
if command -v formail >/dev/null 2>&1; then
DATE_HDR=$(formail -xDate: < "$f" 2>/dev/null)
if [ -n "$DATE_HDR" ]; then
# Convert to epoch seconds if possible
MSG_TIME=$(date -d "$DATE_HDR" +%s 2>/dev/null)
if [ $? -eq 0 ]; then
FILE_TIMES["$f"]="$MSG_TIME"
continue
fi
fi
fi
# Fallback to file modification time
FILE_TIMES["$f"]=$(stat -c %Y "$f")
done
# Find the oldest file (we'll keep its UID)
OLDEST_FILE=""
OLDEST_TIME=9999999999
for f in "${!FILE_TIMES[@]}"; do
if [ "${FILE_TIMES[$f]}" -lt "$OLDEST_TIME" ]; then
OLDEST_TIME="${FILE_TIMES[$f]}"
OLDEST_FILE="$f"
fi
done
echo "Keeping original UID on oldest file: $OLDEST_FILE"
# Rename all newer files by removing the UID part
for f in $DUPLICATE_FILES; do
if [ "$f" != "$OLDEST_FILE" ]; then
# More precise sed pattern to avoid partial UID matches
NEW_NAME=$(echo "$f" | sed "s/,U=$UID_NUM\([,:]\)/, \1/" | sed "s/:2,/,/")
echo "Renaming newer duplicate:"
echo " From: $f"
echo " To: $NEW_NAME"
mv "$f" "$NEW_NAME"
fi
done
echo "Fixed UID collision for UID $UID_NUM. Please run mbsync again."
|