-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsort_media_files.zsh
More file actions
executable file
·111 lines (89 loc) · 2.3 KB
/
sort_media_files.zsh
File metadata and controls
executable file
·111 lines (89 loc) · 2.3 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
#!/usr/bin/env zsh
set -euo pipefail
usage() {
print -u2 "Usage: $0 [directory]"
}
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
usage
exit 0
fi
if [[ $# -gt 1 ]]; then
usage
exit 1
fi
target_dir="${1:-.}"
script_path="${0:A}"
if [[ ! -d "$target_dir" ]]; then
print -u2 "Directory not found: $target_dir"
exit 1
fi
target_dir="${target_dir:A}"
typeset -a photo_exts video_exts
photo_exts=(
jpg jpeg png gif webp heic heif tif tiff bmp
dng raw arw cr2 cr3 nef raf orf rw2 avif
)
video_exts=(
mp4 mov m4v avi mkv webm mpg mpeg mts m2ts
3gp wmv flv ts vob insv
)
is_in_list() {
local needle="$1"
shift
local item
for item in "$@"; do
[[ "$item" == "$needle" ]] && return 0
done
return 1
}
destination_for() {
local file="$1"
local ext="${file:e:l}"
local date_bits year month_name day
if [[ "$file" == "$script_path" ]]; then
return 1
fi
if is_in_list "$ext" "${photo_exts[@]}"; then
date_bits="$(stat -f '%Sm' -t '%Y|%B|%d' "$file")"
IFS='|' read -r year month_name day <<< "$date_bits"
print -- "$target_dir/$year/$month_name/$day/Photo"
return 0
fi
if is_in_list "$ext" "${video_exts[@]}"; then
date_bits="$(stat -f '%Sm' -t '%Y|%B|%d' "$file")"
IFS='|' read -r year month_name day <<< "$date_bits"
print -- "$target_dir/$year/$month_name/$day/Video"
return 0
fi
print -- "$target_dir/Other"
}
unique_path() {
local dir="$1"
local base_name="$2"
local stem="${base_name%.*}"
local ext=""
local candidate="$dir/$base_name"
local counter=1
if [[ "$base_name" == *.* ]]; then
ext=".${base_name##*.}"
else
stem="$base_name"
fi
while [[ -e "$candidate" ]]; do
candidate="$dir/${stem}_$counter$ext"
((counter++))
done
print -- "$candidate"
}
find "$target_dir" \
\( -path "$target_dir/Other" -o -path "$target_dir/Other/*" -o \
-path "$target_dir/[0-9][0-9][0-9][0-9]" -o -path "$target_dir/[0-9][0-9][0-9][0-9]/*" \) -prune -o \
-type f -print0 | while IFS= read -r -d '' file; do
destination_dir="$(destination_for "$file")" || continue
mkdir -p "$destination_dir"
destination_path="$(unique_path "$destination_dir" "${file:t}")"
if [[ "$file" != "$destination_path" ]]; then
print -- "Moving: $file -> $destination_path"
mv "$file" "$destination_path"
fi
done