Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Sort vCards properties according to a custom key

Gmail also sorts X-* properties alphabetically, which is left as an exercise for the reader.
  • Loading branch information...
commit 07a1ed185fd76b7bca50f19f28bcd429bddd72c1 1 parent c62ab55
Victor Engmark authored
Showing with 124 additions and 0 deletions.
  1. +103 −0 sort-lines.sh
  2. +21 −0 sorts/Gmail.re
103 sort-lines.sh
View
@@ -0,0 +1,103 @@
+#!/usr/bin/env bash
+#
+# NAME
+# sort-lines.sh - Sort vCards property lines according to a custom key
+#
+# SYNOPSIS
+# sort-lines.sh KEYFILE FILE...
+#
+# DESCRIPTION
+# Use to minimize the diff between your file and files exported from
+# third party services.
+#
+# EXAMPLES
+# ./sort-lines.sh sorts/Gmail.re ~/contacts/*.vcf
+# Sort properties like a Gmail contact export.
+#
+# BUGS
+# https://github.com/l0b0/vcard/issues
+#
+# COPYRIGHT
+# Copyright (C) 2012 Victor Engmark
+#
+# 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/>.
+#
+################################################################################
+
+set -o errexit -o noclobber -o nounset -o pipefail
+
+dir="$(dirname -- "$(readlink -f -- "$0")")"
+declare -r dir
+
+# Process parameters
+pattern_file="$(readlink -f -- "$1")"
+declare -r pattern_file
+shift
+
+# Working directory
+TMPDIR="${TMPDIR:-/tmp}"
+temporary_dir="$(mktemp -d "$TMPDIR/XXXXXXXXXXXXXXXXXXXXXXXXXXXXX")"
+declare -r temporary_dir
+trap 'rm -rf -- "$temporary_dir"' 0
+trap 'exit 2' 1 2 3 15
+cd -- "$temporary_dir"
+
+lines() {
+ wc -l "$@" | cut -d ' ' -f 1
+}
+
+for file
+do
+ # Split
+ "$dir/split.sh" --digits=8 -- "$file"
+
+ for vcard in xx*
+ do
+ ll_vcard=ll-"$vcard"
+ sorted_ll_vcard=sll-"$vcard"
+ sorted_vcard=s-"$vcard"
+
+ # Join long lines
+ set +o noclobber
+ "$dir/join-lines.sh" "$vcard" > "$ll_vcard"
+ set -o noclobber
+
+ # Match patterns into new file
+ while IFS= read -r -u 9 pattern
+ do
+ set +o noclobber
+ grep -e "$pattern" -- "$ll_vcard" >> "$sorted_ll_vcard" || true
+ set -o noclobber
+ done 9< "$pattern_file"
+
+ # Split long lines
+ set +o noclobber
+ "$dir/split-lines.sh" "$sorted_ll_vcard" > "$sorted_vcard"
+ set -o noclobber
+
+ # Assert that we matched all lines
+ if [ "$(lines "$vcard")" -ne "$(lines "$sorted_vcard")" ]
+ then
+ echo "Unmatched line counts:" >&2
+ diff -u -- "$vcard" "$sorted_vcard" >&2
+ exit 1
+ fi
+ done
+
+ # Restore file
+ set +o noclobber
+ cat -- s-* > "$file"
+ set -o noclobber
+ rm -- *
+done
21 sorts/Gmail.re
View
@@ -0,0 +1,21 @@
+^BEGIN[^A-Z]
+^VERSION[^A-Z]
+^FN[^A-Z]
+^N[^A-Z]
+^NICKNAME[^A-Z]
+^EMAIL[^A-Z]
+^X-
+^TEL[^A-Z]
+^ADR[^A-Z]
+^ORG[^A-Z]
+^TITLE[^A-Z]
+^BDAY[^A-Z]
+^URL[^A-Z]
+^ROLE[^A-Z]
+^NOTE[^A-Z]
+^PHOTO[^A-Z]
+^GEO[^A-Z]
+^TZ[^A-Z]
+^CATEGORIES[^A-Z]
+^END[^A-Z]
+^ $
Please sign in to comment.
Something went wrong with that request. Please try again.