|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +SRC_DB="${HOME}/Library/Safari/History.db" |
| 5 | +DEST_DIR="${HOME}/del" |
| 6 | +DEST_DB_UC="${DEST_DIR}/History.db" |
| 7 | +DEST_DB_LC="${DEST_DIR}/history.db" |
| 8 | +OUT_DIR="${HOME}/data/safair_history" |
| 9 | + |
| 10 | +mkdir -p "$DEST_DIR" "$OUT_DIR" |
| 11 | + |
| 12 | +# Check for sqlite3 |
| 13 | +if ! command -v sqlite3 >/dev/null 2>&1; then |
| 14 | + echo "sqlite3 is required. Install via 'xcode-select --install' or Homebrew." >&2 |
| 15 | + exit 1 |
| 16 | +fi |
| 17 | + |
| 18 | +# Copy the live DB to ~/del using plain cp (your requested method) |
| 19 | +if ! cp -f "$SRC_DB" "$DEST_DB_UC" 2>/dev/null; then |
| 20 | + echo "Could not copy $SRC_DB to $DEST_DB_UC. If denied, grant Terminal Full Disk Access." >&2 |
| 21 | + exit 1 |
| 22 | +fi |
| 23 | + |
| 24 | +# If a lowercase file exists (per your example), prefer it; otherwise use the uppercase one we just wrote. |
| 25 | +DB_TO_QUERY="$DEST_DB_UC" |
| 26 | +if [ -f "$DEST_DB_LC" ]; then |
| 27 | + DB_TO_QUERY="$DEST_DB_LC" |
| 28 | +fi |
| 29 | + |
| 30 | +# Output CSV path with timestamp |
| 31 | + ts="$(date +%Y%m%d_%H%M%S)" |
| 32 | +out_csv="${OUT_DIR}/safari_history_${ts}.csv" |
| 33 | + |
| 34 | +# Query: visits with local timestamps, URL, and title |
| 35 | +SQL=$'SELECT datetime(v.visit_time+978307200,\'unixepoch\',\'localtime\') AS visited_at, i.url FROM history_visits v JOIN history_items i ON i.id=v.history_item ORDER BY v.visit_time DESC;' |
| 36 | + |
| 37 | +if ! sqlite3 -header -csv "$DB_TO_QUERY" "$SQL" > "$out_csv"; then |
| 38 | + echo "sqlite3 query failed on $DB_TO_QUERY." >&2 |
| 39 | + exit 1 |
| 40 | +fi |
| 41 | + |
| 42 | +# Report summary and small preview |
| 43 | +rows=$(wc -l < "$out_csv" | tr -d ' ') |
| 44 | +echo "Copied DB: ${DB_TO_QUERY}" |
| 45 | +echo "Wrote CSV: ${out_csv}" |
| 46 | +echo "Rows (including header): ${rows}" |
| 47 | +echo "Preview:" |
| 48 | +head -n 5 "$out_csv" || true |
0 commit comments