-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate-tarzst.sh
More file actions
executable file
·166 lines (147 loc) · 3.73 KB
/
Copy pathcreate-tarzst.sh
File metadata and controls
executable file
·166 lines (147 loc) · 3.73 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
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]:-$0}")" && pwd)"
# shellcheck source=common.sh
source "${SCRIPT_DIR}/common.sh"
SOURCE_DIR=""
OUTPUT=""
QUIET=0
FORCE=0
REMOVE_SOURCE=0
SHA256_FILE=""
SHA256_ENABLED=0
SHA256_APPEND=0
PZSTD_LEVEL="-10"
usage() {
cat <<'EOF'
Usage:
create-tarzst.sh [options] DIRECTORY
Description:
Streams DIRECTORY into tar (numeric owners) and compresses the tar stream
with the pzstd CLI to produce a seekable .tar.zst archive.
Options:
-o, --output FILE Destination tar.zst path (default: DIRECTORY basename + .tar.zst)
--pzstd-level -#
Override pzstd compression level (default: -10)
--sha256 Emit SHA-256 manifest (default: DIRECTORY basename + .sha256)
--sha256-file FILE
Emit SHA-256 manifest to FILE
--sha256-append Append to the SHA-256 file instead of truncating
--remove-source Delete DIRECTORY after a successful archive
-f, --force Overwrite existing output file
-r, --remove-source Delete DIRECTORY after a successful archive
-q, --quiet Suppress progress logs
-h, --help Show this help message
EOF
}
write_sha256_manifest() {
local root="$1" dest="$2" file rel hash
[[ -z "$dest" ]] && return 0
while IFS= read -r -d '' file; do
rel="${file#$root/}"
if [[ "$rel" == "$file" ]]; then
rel="$(basename -- "$file")"
fi
hash="$(sha256sum -- "$file" | awk '{print $1}')"
printf '%s %s\n' "$hash" "$rel" >>"$dest"
done < <(LC_ALL=C find "$root" -type f -print0 | LC_ALL=C sort -z)
}
while [[ $# -gt 0 ]]; do
case "$1" in
-o | --output)
[[ $# -lt 2 ]] && die "Missing value for $1"
OUTPUT="$2"
shift 2
;;
--pzstd-level)
[[ $# -lt 2 ]] && die "Missing value for $1"
PZSTD_LEVEL="$2"
shift 2
;;
--sha256)
SHA256_ENABLED=1
shift
;;
--sha256-file)
[[ $# -lt 2 ]] && die "Missing value for $1"
SHA256_ENABLED=1
SHA256_FILE="$2"
shift 2
;;
--sha256-append)
SHA256_APPEND=1
shift
;;
-r | --remove-source)
REMOVE_SOURCE=1
shift
;;
-f | --force)
FORCE=1
shift
;;
-q | --quiet)
QUIET=1
shift
;;
-h | --help)
usage
exit 0
;;
--)
shift
break
;;
-*)
die "Unknown option: $1"
;;
*)
if [[ -z "$SOURCE_DIR" ]]; then
SOURCE_DIR="$1"
shift
else
die "Only one directory can be compressed at a time."
fi
;;
esac
done
if [[ $# -gt 0 ]]; then
die "Unexpected positional arguments: $*"
fi
[[ -n "$SOURCE_DIR" ]] || die "Directory path is required."
[[ -d "$SOURCE_DIR" ]] || die "Directory not found: $SOURCE_DIR"
if [[ -z "$OUTPUT" ]]; then
OUTPUT="$(basename -- "$SOURCE_DIR").tar.zst"
fi
if [[ -e "$OUTPUT" && "$FORCE" -ne 1 ]]; then
die "Output already exists: $OUTPUT (use --force to overwrite)"
fi
require_cmd tar
require_cmd pzstd
if [[ "$SHA256_ENABLED" -eq 1 ]]; then
require_cmd sha256sum
fi
mkdir -p -- "$(dirname -- "$OUTPUT")"
if [[ "$SHA256_ENABLED" -eq 1 && -z "$SHA256_FILE" ]]; then
SHA256_FILE="$(default_sha256_path "$SOURCE_DIR")"
fi
if [[ "$SHA256_ENABLED" -eq 1 ]]; then
prepare_file_for_write "$SHA256_FILE" "$SHA256_APPEND"
fi
log "Creating tar.zst at $OUTPUT from $SOURCE_DIR ..."
(
cd "$SOURCE_DIR"
if [[ -z "$(find . -mindepth 1 -print -quit)" ]]; then
tar --numeric-owner -cf - --files-from /dev/null
else
tar --numeric-owner -cf - .
fi
) | pzstd $PZSTD_LEVEL ${FORCE:+-f} -q -o "$OUTPUT"
if [[ "$SHA256_ENABLED" -eq 1 ]]; then
write_sha256_manifest "$SOURCE_DIR" "$SHA256_FILE"
fi
if [[ "$REMOVE_SOURCE" -eq 1 ]]; then
log "Removing source directory: $SOURCE_DIR"
rm -rf -- "$SOURCE_DIR"
fi
log "Done: $OUTPUT"