このスクリプトは実際には使えません。
前回までのあらすじ
最近だと、WindowsとLinuxを動かす時間が同じぐらいになってきたので、
電子書籍作りも、LinuxのフリーソフトであるScribusを使ってやろうと考えていました。
(LibreOfficeでもいいのですが、欧米のフリーの組版ソフトを使ってみたいと思ったので)。
PDFやソフトウェアに(ライセンス的に)埋め込み許可が出ているフォントは、
・・・WindowsでもMACでも、そんなフォントはほぼ皆無なので、
(Microsoft Officeのフォントどころか、標準搭載のフォントですらお金がかかるか不許可)、
フリーフォントを探すことにしました。
フリーフォントだと、埋め込み許可が出ているフォントがたくさんあるので、
たくさんダウンロードしてきました。200個ぐらい。
これだけフォントがあると、展開(圧縮ファイル解凍すること)するだけでも大変です。
展開を自動化しようと思いました。

TeX Wiki フォントの埋め込みとライセンス
https://texwiki.texjp.org/?フォントの埋め込みとライセンス
ゲーム・アプリに組込めるフォントまとめ(トリヘッズ)
https://tktk1.net/other/embedfont/
【2020年版】アプリ/ゲーム開発で使える日本語フリーフォント一覧【再配布可能&記載不要&漢字あり(ゲームUIネット)
https://game-ui.net/?p=797

ここでは、解凍のことを展開と書いています。同じ意味です。

使う機材
Ubuntu MATE 22.10 amd64
ラズパイにはラズパイ用に、armとarm64用のUbuntu MATEがあります。
同じことができます。

コマンドではいっきに全部展開することができない
lzhもzipもtar.gzも、
コマンドで展開することも、GUIを使って展開することもできることはできるのですが、
(lzhの展開はlhasaが必要だけど)
shやbashを使うのは、あまり得意ではないので、
また自動化に強いPythonを使います。

やりたいことは、
・特定のフォルダの中にあるファイル全部を、フォントのあるフォルダにファイルを展開する。
・フォントではないものはフォルダに展開しない。
これだけのことなのですが、何個も何個もフォントがある場合は、
手動でやるのは大変なので、
Pythonにインストーラーになってもらいます。
ラズパイでやるときは特に、ディスク容量に注意しながらやります。
(ちっとも丸くないSSDやmicroSDカードでもディスク扱いとはこれいかに?)
ただし、元のlzh、zip、tar.gzを削除まではしないことにします。
バックアップ用に取っておけるようにはしておいたほうがいいので。

Ubuntu MATEのフォントのフォルダ
これを確認しておかなければ、展開も何もないので。
Ubuntu フォント その2 - フォントファイルのフォーマットとインストール先(kledgeb)
https://kledgeb.blogspot.com/2012/11/ubuntu-2.html
これによれば、/usr/share/fontsと、/usr/local/share/fontsの2つがかかれています。
どちらでもいいのか、それとも両方なのか?
まず、やってみることから始めないと。
sudo caja
このコマンドをやると、権限的に許可がないはずのファイルやフォルダでも、
ファイル操作ができるようになります。


/usr/local/share/fonts に、やさしさゴシックをコピペしました。
うまくいきました。
どうやら、どちらかにコピペすればいいようです。
・・・画像編集用のGIMP使いづらい。

あとはPythonでごりごりやる
Pythonでごりごりやるには、コマンドを遠隔操作するか、
モジュールをインストールするか。
Windowsでもフリーフォントを使いたい。
lzhファイルをどうにかするsubprocessは理解できなかったので、
モジュールを使う方法でやります。
pip install lhafile
地味に忘れがちな7-zip形式も。
pip install py7zr
pip3でインストールできないものは、sudo apt installでインストールします。
なぜかsudo権限だとpipのpy7zrが使えなかった。。。
sudo apt install python3-py7zr
zipはzipfileモジュール、tar.gzはtarfileモジュールが標準で入っていますが、
shutilというモジュールでも、osモジュールとshutilモジュールをインポートすれば、
zip展開、tar.gz展開はやれるらしいですが、
zipはわかっても、
tarファイルはわかんなかったので、tarfileを使うことにいったんしたけど、
zipファイルと同じ方法でshutilでやれるようなので、
tarfileは使わない方法でやっています。

そしてshutilで、ファイルのコピペもやってしまう。
・・・そして一部のzipファイルがどうしても展開できなくなって困ってしまった。
Pythonの意図的な限界らしいです。

プログラムの流れとしては・・・、
フォントのファイルは、拡張子が「ttf」か「otf」です。
私にはttfとotfの違いがわかりません。でもやれれば何でもいい。
ttfファイルやotfファイルだけを圧縮ファイルから抽出することはできないので、
いったんバッファとなるフォルダを作って、
その中でファイルを展開して、
ttfファイル、otfファイルだけを、お目当てのフォントフォルダにコピペする。
そして、展開したフォルダごと、バッファのファイルを消す。
それを全部やるまで繰り返す。
フォルダの中にフォルダが入っていることがあるので、
フォルダを見つけたら、フォルダの中にもぐり、がさごそがさごそ。
そのがさごそするのとかでも手間取っていました。
何回か作り直して、やっとできました。

細かいこと
Pythonがどういう考えなのかわからないけど、
一部のzip形式には対応しません。これはもう仕様です。
仕様なのだから、どうにもできないファイルがいくつか出てきます。
でも、すべてのソフトがフリーソフトでできているはずのUbuntu MATEでも、
問題のzipファイルは手動でzip展開できるから、
ライセンスの問題なのかどうかは、とても微妙です。よくわかりません。

Python的に、Windowsか、MACOSか、Linuxかを識別する方法がありました。
ただ、Linuxはたくさんのディストリビューション(OSの違いに等しいくらいの違いがある何か)があって、
UbuntuやらDebianやらCentOSやらRedHatやらOpenSUSEやらで、
大変なことになるので、
どうせLinuxの人はPython3は、ほぼ使うこと前提なのだから、
GUI化させないままのものをそのまま提供しても問題ないのではないかと思いました。
というわけで、GUI化させないものをここに展示します。

スクリプト
実行すると、量にもよるけど、けっこう時間かかります。
時として、途中で電源が切れないように設定する必要があります。
あと、ラズパイでやるときは特に、容量を気にしてください。
あとでWindowsとMACのために、GUI化やっておきます。
Windowsでやるときは管理者のログインで、
Linuxで実行するときは、必ずsudo権限を使ってやってください。
デリケートなフォルダにアクセスするには、管理者な権限が必要です。
MACでのやり方については・・・私には力不足で再現できませんでした。
どうやってもlhafileモジュールがうまく動いてくれなかった。
おそらく、py7zrもきっと。
あと、一部のzipファイルは、このスクリプトではどうにもできないので、
あとで手動で展開(解凍)して、お目当てのファイルをインストールしてください。
というわけで、MACの人は仕方ないので、自力で動かしてください。
MACは私にはサポートできない。

#必ず管理者権限を使ってやること
import lhafile
import py7zr
import zipfile
import os
import shutil
from pathlib import Path
import re
import string
import random
import platform

#フォルダのパス(必ず最後に「/」をつける)。
#Windowsの場合は、\の代わりに/をつける。または\を\\に書き換える。
#fontsのところに、フォントがあるフォルダの絶対パス、
#omeateのところに、フォントをインストールするフォルダの絶対パスを打ち込む。
fonts="D:/フリーフォント/"
omeate="/usr/local/share/fonts/"
#Windows用
#omeate="C:/Windows/Fonts/"
#MAC用
#omeate="/Library/Fonts/"

#ubuntu用
#omeate="/usr/local/share/fonts/"
#centOS用
#omeate="/usr/share/fonts/"
#ほかは知らない

#プラットフォームを見分けるらしいよ
pf = platform.system()
OS=""
if pf == 'Windows':
    OS=('Windows')
elif pf == 'Darwin':
    OS=('Mac')
elif pf == 'Linux':
    OS=('Linux')

#余計なこと?
if OS=="Windows":
    omeate="C:/Windows/Fonts/"
elif OS=="Mac":
    omeate="/Library/Fonts/"

#バッファになるフォルダの名前。
buf_pasu=""
#フォントのお品書きがメモされるもの
foooo=[]
#終わる許可(圧縮ファイルを全部やっつけたかのフラグ)
kyoka=False
#展開済みとインストール済みのリスト
zumi=[]
#zipファイルによっては展開できないものがある。もうPythonの仕様なんだって。
dame=[]



#展開できなかった圧縮ファイルのリストをテキストファイルにする
#ライセンスの都合上、Pythonでは展開できないzip形式がある。
def dame_desita():
    namae = "あとで手動でインストールするもの.txt"
    if os.path.isdir(fonts + namae)==True:
        shutil.rmtree(fonts + namae)
    #銀盤には特殊なことをしない限り記録できないので、
    #例外規定をつけることにした。
    #特殊なことは、ちょっと普通では無理っぽいし。
    try:
        #なぜかこうやらないと上手にいかなかった。なぜ?
        f = open(fonts + namae, 'w')
        f.close()
        #ファイルを開ける
        f = open(fonts + namae, 'a')
        #実際にリストをファイルに落とす作業
        i=0
        while i<len(dame):
            stri=dame[i].replace(fonts,"")
            f.write(stri+"\n")
            i+=1
        #開けたら絞めるのが決まりらしい
        f.close()
        print("フォントが入っていたフォルダにリストを作ったから。")
        print("これらは、あとで手動でなんとかしてね。")
    except:
        print("リストが用意できなかった。")
    quit()

#バッファフォルダにでたらめな名前をつける
#インストールするデバイスが、外付けに場合はたいてい制限があるので、
#パソコンのHDD(またはSSD)の直下に作ることにした
def namae_wo_tukeru():
    global buf_pasu
    buf_pasu = ''.join(random.choice(string.ascii_uppercase) for _ in range(15))
    if OS=="Linux" or OS=="Mac":
        buf_pasu = "/" + buf_pasu
    elif OS=='Windows':
        buf_pasu = "C:/" + buf_pasu

#バッファフォルダを作る
def baffa_foruda_tukuru():
    global buf_pasu
    namae_wo_tukeru()
    if os.path.isdir(buf_pasu)==True:
        namae_wo_tukeru()
    else:
        os.mkdir(buf_pasu)

#バッファフォルダを消す
def baffa_foruda_kesu():
    global buf_pasu
    shutil.rmtree(buf_pasu)
    print("一時ファイルを消した。")

#サブディレクトリも含めたフォルダの中身を調べるfor文
#ほとんどコピペした
#aieeeはお目当てのフォルダのパス、ughhhはリスト
def foruda_no_nakami_zenbu( aieee ):
    ughhh=[]
    for current_dir, sub_dirs, files_list in os.walk( aieee ):
        for file_name in files_list:
            ughhh.append(os.path.join(current_dir,file_name))
    return ughhh

#査読してリストを訂正する
def seisa(ughhh):
    global zumi
    i=0
    j=0
    while i<len(zumi):
        while j<len(ughhh):
            if zumi[i]==ughhh[j]:
                ughhh[j]="イク!"
                zumi[i]="やったぜ!"
            j+=1
        j=0
        i+=1
    return ughhh

#圧縮ファイルを展開(解凍)するためのもの
#aieeeにはバッファフォルダのパス、ughhhにリストを渡すこと
def tenkai_suru( aieee,ughhh ):
    global zumi
    ughhh = seisa(ughhh)
    i=0
    while i<len(ughhh):
        #査読して訂正してもらう必要がある
        #7zipの展開は60%ぐらいコピペした
        if ughhh[i].endswith(".7z")==True or ughhh[i].endswith(".7Z")==True:
            zumi.append(ughhh[i])
            print(ughhh[i]+"を調べ中。")
            # 7zファイルを解凍
            with py7zr.SevenZipFile(ughhh[i], mode='r') as archive:
                archive.extractall(path=buf_pasu)
                
        #lha圧縮なんてややこしい名前がついているlzhファイル
        elif ughhh[i].endswith(".lzh")==True or ughhh[i].endswith(".LZH")==True:
            zumi.append(ughhh[i])
            print(ughhh[i]+"を調べ中。")
            #スクリプトを理解できなかったので75%くらいコピペ
            f = lhafile.Lhafile(ughhh[i])
            #os.makedirs(extract_dir, exist_ok=True)
            for info in f.infolist():
                fname = info.filename
                with open("{}/{}".format(buf_pasu, fname), "wb") as tf:
                    tf.write(f.read(info.filename))

        #zipファイルのも例にもれなくコピペした
        elif ughhh[i].endswith(".zip")==True or ughhh[i].endswith(".ZIP")==True:
            zumi.append(ughhh[i])
            print(ughhh[i]+"を調べ中。")
            #この方式で展開できないファイルがあったので、
            #別の方法で試してみたけどこれでもだめだった。
            #shutil.unpack_archive(ughhh[i], buf_pasu)
            try:
                # ZIPファイルを読み込み
                zip_f = zipfile.ZipFile( ughhh[i] )
                # ZIPを解凍
                zip_f.extractall( buf_pasu )
            except:
                print(ughhh[i]+"を倒せないよう!")
                dame.append(ughhh[i])
        #tarファイルの展開はzipと同じ方法でいいみたい
        elif ughhh[i].endswith(".tar.gz")==True:
            zumi.append(ughhh[i])
            print(ughhh[i]+"を調べ中。")
            shutil.unpack_archive(ughhh[i], buf_pasu)
        elif ughhh[i].endswith(".tar.xz")==True:
            zumi.append(ughhh[i])
            print(ughhh[i]+"を調べ中。")
            shutil.unpack_archive(ughhh[i], buf_pasu)

        #何も表示しないと水面下で何が起きてるか不安になる
        i+=1

#リストの中身を調べる
def siraberu( ughhh ):
    huragu=True
    i=0
    while i<len(ughhh):
        if ughhh[i].endswith(".tar.xz")==True or \
         ughhh[i].endswith(".tar.gz")==True or \
         ughhh[i].endswith(".zip")==True or \
         ughhh[i].endswith(".ZIP")==True or \
         ughhh[i].endswith(".lzh")==True or \
         ughhh[i].endswith(".LZH")==True or \
         ughhh[i].endswith(".7z")==True or \
         ughhh[i].endswith(".7Z")==True :
         huragu=False
        i+=1
    return huragu
    
#フォントをインストールする
#aieeeにはフォントがあるはずのフォルダ、
#ughhhにはフォントのお品書きがかかれているリストを渡す
def fonto_wo_insutooru( aieee , ughhh):
    global omeate,buf_pasu
    
    i=0
    while i<len(ughhh):
        if ughhh[i].endswith(".ttf")==True or \
         ughhh[i].endswith(".TTF")==True or \
         ughhh[i].endswith(".otf")==True or \
         ughhh[i].endswith(".OTF")==True :
            shutil.copy( ughhh[i] , omeate )
            print(ughhh[i]+"をインストールしたぜ。")
        i+=1

#おわり
def owari():
    baffa_foruda_kesu()
    if int(len(dame))!=0:
        i=0
        print("\n\n\n中が調べられなかったファイルがあるぜ。")
        while i<len(dame):
            print(dame[i]+"は、無理だったぜ。")
            i+=1
        dame_desita()
    else :
        print("全員かたづけたぜ!")

#関数まとめる
def zenbu_yattukeru():
    global foooo,fonts,omeate,buf_pass,madaaru,kyoka,zumi
    #そもそも始めているかどうかがわからない
    print("いくぜ!")
    
    #まず入れたいフォントがあるフォルダのリストをつくる
    foooo = foruda_no_nakami_zenbu( fonts )
    #入れたいフォントには生のフォントファイルもあるだろうから
    fonto_wo_insutooru( fonts , foooo )
    #バッファフォルダを作る。バッファフォルダの名前も決まる
    baffa_foruda_tukuru()
    #ファイルをいったん全部展開する
    tenkai_suru(fonts , foooo)
    #リストを調べる
    kyoka=siraberu(foooo)
    while kyoka==False:
        #今度はbuf_passの中のファイルを調べてリストを作る
        foooo = foruda_no_nakami_zenbu( buf_pasu )
        #ファイルをいったん全部展開する
        tenkai_suru(buf_pasu , foooo)
        #リストを調べる
        kyoka=siraberu(foooo)
    fonto_wo_insutooru( buf_pasu , foooo )
    owari()

zenbu_yattukeru()

その他の参考資料
PythonでLZHファイルを展開してみる(Developers IO)
https://dev.classmethod.jp/articles/python_lzh/
PythonでZIPファイルを圧縮・解凍するzipfile(note.nkmk.me)
https://note.nkmk.me/python-zipfile/
Python Tips: アーカイブファイル( .zip .tar.gz )を扱いたい(Life with Python)
https://www.lifewithpython.com/2021/09/python-archive-files.html
【Python】7zファイルを解凍するプログラムの書き方(アシタリッチ)
Python ファイル操作(Windows)(トッカンソフトウェア)
Pythonでファイルの圧縮&解凍(tar編)|圧縮解凍(purpledice.jp)
ラズパイ(Raspberry Pi)でスクリーンショットを撮るベストな方法は? コマンドラインのscrot? それともGUIのgnome-screenshot?(DevicePlus)
Pythonで文字列が含むか検索する4つの方法!(コードライク)
Pythonで文字列の一部を削除(stripなど)(note.nkmk.me)
ランダムな文字列を生成する(Visual Basic 中学校 Python サンプル集)
https://www.umayadia.com/pysample/sample0201/Sample230RandomString.htm
Pythonで文字列を比較(完全一致、部分一致、大小関係など)(note.nkmk.me)
https://note.nkmk.me/python-str-compare/
zip - ファイルを圧縮 - Linuxコマンド(Webkaru)
https://webkaru.net/linux/zip-command/
【Python】ZIPファイルを解凍する(鎖プログラム)
https://pg-chain.com/python-zipfile-2
【Windows 10・11】フォントフォルダの場所はどこ?保存場所を開く方法(G-NOTE)
https://316-jp.com/windows-font-folder
「Mac」のフォント保存場所がわからない? 追加インストールしたフォントは?(オトナライフ)
https://otona-life.com/2021/04/08/60527/
MacBookのターミナルでUSBメモリにアクセスする方法
https://daiiz.hatenablog.com/entry/2015/03/09/233814
LGPL【ライセンス】(「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典)
https://wa3.i-3-i.info/word13201.html
【Python】tkinterでGUIの画面を作成する!(フライテック)
https://flytech.work/blog/16310/
OS(プラットフォーム)の判別(Python)(渥美剛史)
https://www.atsumitakeshi.com/python/py_os_discrim.html Windowsで圧縮した巨大zipがPythonで展開/解凍できない!(たれぱんのびぼーろく)
https://tarepan.hatenablog.com/entry/2018/11/18/035326
【Python】テキストファイルの新規作成・読み込み・書き込み(追記)の方法(OFFICE54)
https://office54.net/python/basic/python-textfile-create
Python-サブディレクトリを含めたディレクトリ配下の全ファイル一覧を取得する方法(liquid jumper)