2021/10/24
本記事のスクリプトは自由に複製・改変して実行していただいて構いませんが,
それによって生じた損害等の一切の責任は負いかねます.
私自身の環境で動作するために開発しているため,
悪意無く開発しており,
当環境における動作確認は出来ております.
しかし,コンピュータに影響を及ぼすスクリプトですので,
全て自己責任の元でお使い頂くよう,
よろしくお願いいたします.
はじめに
メインのデスクトップにUbuntuを使っていて,たまにbackups
を使ってバックアップを取っている.
そして私は,Pythonの実行環境の整備にはvenv
を,Node.jsにはもちろんnpmを使っている.
その上でバックアップを取ると,どうしても大量の.venv
およびnode_modules
が気になってしまう.
以前,解消方法を模索したことがあり,その時はbackups
のFolders to ignore
にワイルドカードが使えるという情報をどこかで見て,設定して試してみたのだが,どうやら適用されていなかったようで,断念した.
今回は,ディスク容量含め抜本的な解決を目指し,シェルスクリプトの関数を作ってみた.
要件
当然,情報量を極力減らさない方法での解決を目指す.
venvの場合
私は普段,Pythonの環境を作成する際には,決まってpython -m venv .venv
を使っている.
このように統一することで,カレントディレクトリに.venv
がある時に自動アクティベートするという恩恵を得られる.
.venv
を消すと,対象の実行環境はきれいに削除される.
また,上述したコマンドでは,クリーンなPython環境が作成され,インストールしてあるパッケージのみで動作可能という前提がある.
pip
には,適切な形式のrequirements.txt
に対し,pip -r requirements.txt
と実行することで,パッケージのバージョンを揃えてくれる機能がある.
requirements.txt
は,pip freeze
により生成でき,これによって今のパッケージバージョンを全て記録できる.
npmの場合
npmパッケージのローカルインストールは,package.json
にパッケージ情報が保存され,package-lock.json
に詳細なパッケージバージョンを含む情報が保存される.
そして,パッケージの実態は./node_modules
内に全て保存される.
ここで,./node_modules
にあるものは全て,npmが存在している限りpackage-lock.json
から復元可能である.
つくるのは
以上の前提の元,venvおよびnpmに対して必要な処理が決まった.
.venv
を見つけ,pip freeze
で環境情報をテキストに保存し,.venv
を削除node_modules
を削除- 両者に対し,検出時に削除の可否を求める
スクリプト
function clear_python_venv() {
source $1/${python_venv_key}/bin/activate
pip freeze > $1/requirements.txt
deactivate
rm -r $1/${python_venv_key}
}
function clear_node_modules() {
rm -r $1/${node_env_key}
}
function detect_venvs_and_clear() {
if [ -e "$1/${python_venv_key}" ]; then
echo ""
echo "Detect ${python_venv_key} in $1"
read -p "Do you clear? [y/N]" -r
if [[ ! $REPLY =~ ^[yN]$ ]]; then
return
fi
echo "Clearing ${python_venv_key} in $1"
clear_python_venv $1
fi
if [ -e "$1/${node_env_key}" ]; then
echo ""
echo "Detect ${node_env_key} in $1"
read -p "Do you clear? [y/N]" -r
if [[ ! $REPLY =~ ^[yN]$ ]]; then
return
fi
echo "Clearing ${node_env_key} in $1"
clear_node_modules $1
fi
}
function detect_venvs_and_clear_recurse() {
detect_venvs_and_clear $1
directories=$(find ${1} -maxdepth 1 -type d -not -name ".*")
for directory in ${directories[@]}
do
if [[ $directory == $1 ]];then
continue
fi
if [[ $directory == "$1/${node_env_key}" ]];then
continue
fi
detect_venvs_and_clear_recurse $directory
done
}
function clear_venvs_recurse() {
python_venv_key='.venv'
node_env_key='node_modules'
search_path=$PWD
detect_venvs_and_clear_recurse $search_path
}
コードの解説
スクリプトの内部が気になる方向けの簡単紹介.
venvの記録と削除
pip freeze
すると,「現在の」pipでインストールされたパッケージが吐き出されるため,対象となる.venv
を起動する必要がある.
そこで,探索ディレクトリの.venv/bin/activate
から実行環境を起動し,pip freeze
する.
そして,忘れずにdeactivate
をした後,.venv
を削除する.
function clear_python_venv() {
source $1/${python_venv_key}/bin/activate
pip freeze > $1/requirements.txt
deactivate
rm -r $1/${python_venv_key}
}
node_modulesの削除
node_modules
を削除する.
function clear_node_modules() {
rm -r $1/${node_env_key}
}
検出とクリア
探索ディレクトリ内に.venv
/node_modules
を検出した場合,y/N
を質問する.
安全のため,デフォルトはNoにしており,y/Yのどちらかが入力された場合に,環境を削除する.
function detect_venvs_and_clear() {
if [ -e "$1/${python_venv_key}" ]; then
echo ""
echo "Detect ${python_venv_key} in $1"
read -p "Do you clear? [y/N]" -r
if [[ ! $REPLY =~ ^[yN]$ ]]; then
return
fi
echo "Clearing ${python_venv_key} in $1"
clear_python_venv $1
fi
if [ -e "$1/${node_env_key}" ]; then
echo ""
echo "Detect ${node_env_key} in $1"
read -p "Do you clear? [y/N]" -r
if [[ ! $REPLY =~ ^[yN]$ ]]; then
return
fi
echo "Clearing ${node_env_key} in $1"
clear_node_modules $1
fi
}
再帰的な検出とクリア
内部で再帰的に呼ばれる関数.
$1
は探索対象となるディレクトリとした.
呼び出し時に,.venv
/node_modules
を検出し,削除を確認し,処理する.
find
コマンドにより探索ディレクトリ内のディレクトリを新しい探索ディレクトリとし,再帰する.この時,隠しファイルとなっているディレクトリは無視する.
また,node_modules
の中には無数のnode_modules
が含まれており,それを内包するnode_modules
を削除せずに内部の特定のnode_modules
を削除するパターンは基本的に無いと考え,探索対象から除外する.
function detect_venvs_and_clear_recurse() {
detect_venvs_and_clear $1
directories=$(find ${1} -maxdepth 1 -type d -not -name ".*")
for directory in ${directories[@]}
do
if [[ $directory == $1 ]];then
continue
fi
if [[ $directory == "$1/${node_env_key}" ]];then
continue
fi
detect_venvs_and_clear_recurse $directory
done
}
呼び出し用関数
シェルスクリプトからの呼び出しに便利なように,再帰関数を囲む関数を準備した.
実際に呼び出す関数はこれになる.
利便性向上の為,キーをここで指定する.
function clear_venvs_recurse() {
python_venv_key='.venv'
node_env_key='node_modules'
search_path=$PWD
detect_venvs_and_clear_recurse $search_path
}
おわりに
シェルスクリプト書くのまじつらい・・・
繰り返しになりますが,
コードは自由に複製・改変いただけますが,
全て自己責任でご利用ください.