]> Sergey Matveev's repositories - torn.git/blob - torn.zsh
d9900de9acb1aac5af1764ca02df1f87ab837fdd
[torn.git] / torn.zsh
1 # torn - Musical files renaming with russian language transliteration
2 # Copyright (C) 2021-2024 Sergey Matveev (stargrave@stargrave.org)
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, version 3 of the License.
7
8 # Initially this script was written on Perl, but now it is Z shell
9 # function, that is intended to be used with zmv command. It is much
10 # more flexible to be used with zsh'es glob expansion.
11 #
12 # * transliterates everything
13 # * replaces non FAT-compatible characters with underscores
14 # * replaces spaces with underscores
15 # * lowercases file's extension
16 # * replaces "_-_" with single dash
17 # * removes spaces before and after brackets
18 # * removes space after comma
19 # * removes "[]" brackets
20 # * replaces ampersand with "and" word
21 #
22 # You can run like that:
23 #   $ fpath=(... $fpath)
24 #   $ autoload torn
25 #   $ zmv "*" '`torn $f`"
26 #
27 # Transliteration function is separate tornt(), so you can use only
28 # its abilities:
29 #   $ torn # assume that it is not autoloaded
30 #   $ zmv "*" '`tornt $f`'
31 #
32 # torna() replaces non FAT-compatible characters with underscores.
33 #
34 # Recursively dive into subdirectories:
35 #   $ zmv -Q "(**/)*(.)" '`torn $f`'
36
37 tornt() {
38     local n=$1
39     local rusS=абвгдеёзийклмнопрстуфхцьъыэ
40     local engS=abvgdeezijklmnoprstufhcjjye
41     for i ({1..${#rusS}}) {
42         eval n=\${n:gs/${rusS[$i]}/${engS[$i]}}
43         eval n=\${n:gs/${(U)rusS[$i]}/${(U)engS[$i]}}
44     }
45     local rusL=( ж  ч  ш   щ  я  ю  Ж  Ч  Ш   Щ  Я  Ю)
46     local engL=(zh ch sh sch ja ju Zh Ch Sh Sch Ja Ju)
47     for i ({1..${#rusL}}) eval n=\${n:gs/${rusL[$i]}/${engL[$i]}}
48     print -- $n
49 }
50
51 tornm() {
52     local n=$1
53     n=${n:gs/ /_}
54     n=${n//_[–-]_/-}
55     n=${n//_[–-]/-}
56     n=${n//[–-]_/-}
57     n=${n:gs/,_/,}
58     n=${n//[\[\]]/}
59     n=${n:gs/_(/(}
60     n=${n:gs/-(/-}
61     n=${n:gs/(_/(}
62     n=${n:gs/)_/-}
63     n=${n:gs/_)/)}
64     n=${n:gs/&/and}
65     [[ $n =~ "\." ]] && n=${n:r}.${(L)n:e}
66     [[ $n =~ "^([[:digit:]]+)[-.]_*(.+)$" ]] && n="$match[1].$match[2]"
67     print -- $n
68 }
69
70 torna() {
71     local n=$1
72     setopt REMATCH_PCRE
73     for i ({1..${#n}}) {
74         [[ ${n[$i]} =~ "[[:ascii:]]" ]] || n[$i]=_
75         [[ ${n[$i]} =~ "[[:print:]]" ]] || n[$i]=_
76         [[ ${n[$i]} =~ "[^,+/:;<=>?[]|]" ]] || n[$i]=_
77     }
78     print -- $n
79 }
80
81 [[ -n $1 ]] || return
82 local n=${1:t}
83 n=`tornm $n`
84 n=`tornt $n`
85 n=`torna $n`
86 print -- ${1:h}/$n