WSLのパッケージ管理を確認する
Linuxを使ってきた方がBUW(Bash on Ubuntu on Windows)を使っていて不思議に思うのは、パッケージの更新ではないだろうか。WSL(Windows Subsystem for Linux)は、UbuntuというLinuxディストリビューションをそのまま取り込んでいるため、Debian GNU/Linux系のパッケージ管理コマンドである「apt-get」を使用する。より新たな「apt」コマンドもインストールされているが、慣例的な操作を行うのであれば、前者の方が参考資料も多く覚えやすい。
「sudo apt-get update -y」と入力して[Enter]キーを押すと、rootアカウント(正確には最初に設定した)パスワードの入力を求められる。そのまま入力して[Enter]キーを押すと、利用可能パッケージの一覧が更新される |
直後に「sudo apt-get upgrade -y」と入力して[Enter]キーを押せば、利用可能パッケージのダウンロードとインストールが始まる。一定時間が経つとrootアカウントのパスワード再入力を求められるので注意してほしい |
上図のとおりBUWも、他のLinuxディストリビューションと同じくパッケージを更新できる。だが、更新したパッケージの中にはセキュリティホールを塞いだものもあるため、早期の適用が必要なるケースも少なくない。パッケージの自動更新は「cron-apt」パッケージなどで実現可能ながらも、WSLは「開発者が使用するLinux環境であり、サーバー機能は対象外」とMicrosoftが明言しているとおり、現バージョンは指定時間にコマンドやシェルスクリプトを実行するcrontabは使用できない。
そこでMicrosoftが用意したのが「AptPackageIndexUpdate」というタスクだ。タスクスケジューラーの「\Microsoft\Windows\Windows Subsystem for Linux」フォルダーに登録されたAptPackageIndexUpdateは、実行タイミングこそ不明だが、「%comspec% /c start "AptPackageIndexUpdate" /min %windir%\System32\LxRun.exe /update」というコマンドを実行している。
「LxRun.exe」は第4回でも紹介したように、WSLのインストールや再インストール、既定ユーザーの設定を行うコマンドだ。オプションの1つ「update」からも分かるように、パッケージの更新を行うようだが、筆者の環境(Windows 10 Insider Preview ビルド14905.1000)では、エラーコード0x41303が発生してタスクを実行している気配がない。
そこで「lxrun /update」を手動実行してみたところ、確かに利用可能なパッケージの一覧は更新されるものの、肝心のパッケージをダウンロードする気配がない。上図のコマンドヘルプにも「パッケージのインデックスを更新する」としか書かれていないため、正しい動作と思われる。だが、肝心のパッケージがインストールされないのでは意味がない。WSLはベータ版であり、Ubuntu自身も14.04 LTSと古いバージョンを用いている。時期は不明ながらも正式版リリース時は、Windows 10上でパッケージの自動更新なども動作するのではないだろうか。
散らかったデスクトップを片付ける
さて、今回から新しいシェルスクリプトにチャレンジしよう。いつもどおり担当編集者と打ち合わせし、同氏が持ち込んでいたノートPCへ何気になく目を向けると、デスクトップに前回の原稿やシェルスクリプト、画像ファイルが散乱しているのだ。デスクトップ管理は人によって千差万別で、使用頻度の高いアプリケーションのショートカットファイルを並べている方もいれば、作業中のフォルダーを山ほど並べている方もいる。かく言う筆者は長年デスクトップを作業領域と認知しているため、脱稿した時点で特定のフォルダーに移動するタイプだ。
そこで担当編集者に提案したのが、デスクトップ上のファイルを自動整理するシェルスクリプトである。構造自体は簡単でデスクトップに並ぶファイルを拡張子ベースでサブフォルダーに振り分けていけばよい。ちょうど本連載第1回から作成してきたシェルスクリプトに類似し、行うアクションを変更すれば簡単に書けそうだ。その条件として最初に決めておきたいのが、シェルスクリプトの仕様である。
まず、拡張子「.jpg」などを持つファイルは「Photos」フォルダーに移動。拡張子「.zip」や「.exe」を持つファイルは展開や実行した後は不要な存在になるはずだが、今回は「Packages」フォルダーに移動。拡張子「.txt」「.pdf」などは「Documents」フォルダーに移動する。ただし、前述のようにプロジェクトごとにサブフォルダーを作成する場合や、アプリケーションのショートカットファイルを並べる方が多いことを踏まえ、拡張子「.lnk」やフォルダーは移動対象外とすることにした。それでは、いつもどおりvimなどで下記の内容を作成し、chmodコマンドで実行権限を付加してほしい。
#!/bin/bash
BaseDir="/mnt/c/Users/kaz/Desktop/Test"
PhotosDir="./Photos"
PackagesDir="./Packages"
DocDir="./Documents"
cd $BaseDir
for File in *; do
case ${File##*.} in
jpg|JPG|png|PNG )
if [ ! -d $PhotosDir ]; then
mkdir $PhotosDir
fi
find . -maxdepth 1 \( -iname '*.jpg' -or -iname '*.png' \) -exec mv {} -t $PhotosDir \;
;;
zip|ZIP|exe|EXE )
if [ ! -d $PackagesDir ]; then
mkdir $PackagesDir
fi
find . -maxdepth 1 \( -iname '*.zip' -or -iname '*.exe' \) -exec mv {} -t $PackagesDir \;
;;
txt|TXT|pdf|PDF )
if [ ! -d $DocDir ]; then
mkdir $DocDir
fi
find . -maxdepth 1 \( -iname '*.txt' -or -name '*.pdf' \) -exec mv {} -t $DocDir \;
;;
*) ;;
esac
done
今回は実験環境としてWindows 10のデスクトップフォルダーに「Test」フォルダーを作成し、その上にダミーファイルを用意して検証を行っている。そのため、3行目にある変数「BaseDir」の内容はお使いの環境に合わせて変更してほしい。基本的には流れは以前紹介したシェルスクリプトと同様に、変数BaseDir上のディレクトリ(フォルダー)のファイル名から拡張子を取り出し、case文で処理を振り分けている(10~29行)。
今回のポイントは15/21/27行目で用いている「find」コマンドだ。利用者が指定した条件にマッチするファイルを探すコマンドだが、今回は大文字小文字を無視する「-iname」と条件演算子である「-or」オプションを組み合わせ、同じカテゴリーとなる拡張子をピックアップしている。その結果を「-exec」オプションで「mv」コマンドに渡す仕組みだ。なお、「-maxdepth」は検索階層を示し、今回の例では1階層目まで検索を行っている。
もう1つのポイントはmvコマンドの「-t」オプション。「--target-directory」と記述するこのオプションは、すべてのソース引数をディレクトリに移動するというもの。今回のシェルスクリプトを検証していたところ、移動先となるディレクトリをファイルとして上書きする現象が確認されたため、安全策として付与している。ちなみにシェルスクリプトが作成するフォルダー名を変更する場合は5~7行目の変数値を変更し、拡張子のパターンを増やす場合はfindコマンドで指定した-inameオプションを追加するとよい。
さて、前述のとおり特定の拡張子を持つファイルを、カテゴリーごとに作成したフォルダーに移動しているが、タイプミスなどでバグが侵入し、大事なファイルを消失してしまう可能性は拭い切れない。その際は「mv」コマンドを「cp」に置き換えてからテストすることで、"移動"が"コピー"に変化するのでシェルスクリプトの動作を確認できる。次回はシェルスクリプトの最適化と、ちょっとしたアイディアを加えて利便性を向上させてみよう。
阿久津良和(Cactus)