Repository navigation
Expand file tree
/
Copy pathdashcam_sync.sh
More file actions
executable file
·185 lines (166 loc) · 6 KB
/
Copy pathdashcam_sync.sh
File metadata and controls
executable file
·185 lines (166 loc) · 6 KB
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
#!/bin/sh
########################################################################
# dashcam_sync.sh: Dashcam Files Management Script
#
# Description:
# This script synchronizes dashcam files from a local directory to an
# external drive and organizes them into a yearly structured folder. It
# requires a configuration file named 'dashcam_sync.conf' for specifying
# source and destination directories.
#
# Author: id774 (More info: https://id774.net)
# Source Code: https://github.com/id774/scripts
# License: The GPL version 3, or LGPL version 3 (Dual License).
# Contact: idnanashi@gmail.com
#
# Usage:
# Run the script without any arguments. Ensure that 'dashcam_sync.conf'
# is properly set up with SOURCE_DIR and DEST_DIR variables.
# ./dashcam_sync.sh
#
# Configuration file ('dashcam_sync.conf') requirements:
# - SOURCE_DIR: Directory containing the dashcam files to be synchronized.
# - DEST_DIR: Destination directory on the external drive for synchronized files.
# Ensure both variables are set in 'dashcam_sync.conf'.
#
# Notes:
# - Both source and destination directories must exist and be writable.
# - Files are first synced to a 'daily' subdirectory, then moved to a yearly directory.
#
# Exit Status:
# 1. Source or destination directory does not exist.
# 2. Rsync operation failed.
# 3. Moving files failed.
# 4. Configuration file not found.
# 5. One or more configuration variables not set.
#
# Version History:
# v2.1 2026-09-20
# Align move detection with the entries actually moved and preserve
# mv failure diagnostics.
# v2.0 2026-07-11
# Replace the awk {n,} interval expression in usage() with a portable
# equivalent, since mawk on some systems matches it incorrectly.
# v1.8 2026-07-08
# Create the destination yearly directory before moving files so that
# the first run of a new year no longer fails with a move error.
# v1.7 2025-06-23
# Unified usage output to display full script header and support common help/version options.
# v1.6 2025-04-13
# Unify log level formatting using [INFO], [WARN], and [ERROR] tags.
# v1.5 2025-03-22
# Unify usage information by extracting help text from header comments.
# v1.4 2025-03-17
# Encapsulated all logic into functions and introduced main function.
# v1.3 2025-03-16
# Redirected error messages to stderr for better logging and debugging.
# Make POSIX compliant by removing 'local' variables.
# v1.2 2024-02-08
# Enhanced documentation, added configuration variable checks, and
# improved error handling and script structure.
# v1.1 2023-12-23
# Updated to load source and destination directories from an external configuration file located in 'etc' or
# '../etc'. Added file existence check in move_files function to prevent errors when no files are available to move.
# v1.0 2023-12-05
# Initial release.
#
########################################################################
# Display full script header information extracted from the top comment block
usage() {
check_commands awk
awk '
BEGIN { in_header = 0 }
/^#+$/ && length($0) >= 10 { if (!in_header) { in_header = 1; next } else exit }
in_header && /^# ?/ { print substr($0, 3) }
' "$0"
exit 0
}
# Check if required commands are available and executable
check_commands() {
for cmd in "$@"; do
cmd_path=$(command -v "$cmd" 2>/dev/null)
if [ -z "$cmd_path" ]; then
echo "[ERROR] Command '$cmd' is not installed. Please install $cmd and try again." >&2
exit 127
elif [ ! -x "$cmd_path" ]; then
echo "[ERROR] Command '$cmd' is not executable. Please check the permissions." >&2
exit 126
fi
done
}
# Determine the script's directory
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# Load configuration
load_configuration() {
CONF_FILE="$SCRIPT_DIR/etc/dashcam_sync.conf"
if [ ! -f "$CONF_FILE" ]; then
CONF_FILE="$SCRIPT_DIR/../etc/dashcam_sync.conf"
if [ ! -f "$CONF_FILE" ]; then
echo "[ERROR] Configuration file not found." >&2
exit 4
fi
fi
. "$CONF_FILE"
# Check if necessary variables are set
if [ -z "$SOURCE_DIR" ] || [ -z "$DEST_DIR" ]; then
echo "[ERROR] SOURCE_DIR or DEST_DIR not set in configuration." >&2
exit 5
fi
}
# Check if source and destination directories exist
check_directories() {
if [ ! -d "$SOURCE_DIR" ] || [ ! -d "$DEST_DIR" ]; then
echo "[ERROR] Source or destination directory does not exist." >&2
exit 1
fi
}
# Synchronize files using rsync
sync_files() {
echo "[INFO] Synchronizing files to $DEST_DIR..."
rsync -avz --delete "$SOURCE_DIR/" "$DEST_DIR/daily/"
if [ $? -ne 0 ]; then
echo "[ERROR] Rsync failed." >&2
exit 2
fi
}
# Move files to a yearly directory
move_files() {
src="$1"
dest="$2"
# Expand the top-level entries once and reuse the same set for the
# no-work check and the move itself, so both operate on the same files.
set -- "$src"/*
# Check if there are files to move
if [ "$#" -eq 1 ] && [ "$1" = "$src/*" ]; then
echo "[WARN] No files to move from $src." >&2
return 0
fi
# Ensure the destination directory exists before moving
if [ ! -d "$dest" ]; then
if ! mkdir -p "$dest"; then
echo "[ERROR] Failed to create destination directory '$dest'." >&2
exit 3
fi
fi
echo "Moving files from '$src' to '$dest'..."
if ! mv "$@" "$dest/"; then
echo "[ERROR] Moving files failed." >&2
exit 3
fi
}
# Main entry point of the script
main() {
case "$1" in
-h|--help|-v|--version) usage ;;
esac
load_configuration
check_directories
YEAR_DIR="$(date +"%Y")"
sync_files
move_files "$DEST_DIR/daily" "$DEST_DIR/$YEAR_DIR"
move_files "$SOURCE_DIR" "$SOURCE_DIR/../$YEAR_DIR"
echo "[INFO] Operation completed successfully."
return 0
}
# Execute main function
main "$@"