Windows 10 Anniversary UpdateからサポートしたWSL(Windows Subsystem for Linux)。その結果としてWindows 10上でもBUW(Bash on Ubuntu on Windows)が動作し、各種Linuxコマンドが利用可能になった。本連載ではWSLに関する情報や、Bashから実行するシェルスクリプトを紹介する。

最新のWSLはシリアルデバイスをサポート

既に多く方がWindows 10 バージョン1703(Creators Update)に更新されたと思うが、Windows 10 Insider Preview上のBUWは、着々と進化を遂げている。ビルド16170では、マルチキャストグループに参加するIP_ADD_MEMBERSHIP及びIPV6_ADD_MEMBERSHIPをソケットオプションでサポート。ビルド16176では、/mnt/cなどWSLからNTFSへアクセスする際に用いるdrvfsで、UNCやCDFS、FAT、リモートドライブなどをサポートしている。

「ls /dev/ttyS*」の実行結果

さらに同ビルドはシリアルデバイス(COMポート)のサポートが行われた。公式ブログによれば、/dev/ttyS[N]をCOM[N+1]にマッピングし、/dev/ttyS0を叩けばCOM1を利用できるという。Microsoftは本機能で実現するシナリオとして、BUWからUSBシリアルドライバーを叩くプログラムの実現や、cuコマンドを使ったRaspberry Pi 2シリアル端末への接続、Hyper-V仮想COMポートなどを経由したデータ転送が可能になると説明した。

WSLとWindows 10 COMポートの関係図(公式ブログより抜粋)

Linuxでシリアル通信を行うシーンはネットワークハブやルーターのメンテナンスを行う際、日常的に行われてきたが、BUW上でも同様の作業が可能になることで、開発者の利便性は大きく高まりそうだ。

1週間のファイルをISOファイルに書き込む

さて、以前の連載で当日に変更を加えたファイルを列挙し、アプローチを行うシェルスクリプトを紹介した。findコマンドを使うことで指定した拡張子を持つファイルのみを抽出するというものだが、その応用編として「1週間前までのファイルをピックアップして、ISOイメージにバックアップ」するシェルスクリプトを作成したい。

LinuxでISOイメージファイルを作成する場合、mkisofsコマンドを使うのが通例だと思っていたが、それは筆者が学んだ1990~2000年代までの常識らしい。最近はフォーク版であるgenisoimageを含むcdrkitを使うようだ。ちなみにcdrkit自体もcdrtoolsのフォーク版にあたる。BUWにはcdrkitは含まれていないものの、今回は光学メディアへ書き込みを行うwodimなどは必要ないため、genisoimageのパッケージのみインストールすることにした。

「sudo apt install genisoimage」を実行して、対象パッケージをインストールする

これで下記に示したシェルスクリプトが実行可能になる。後はいつもどおり任意のテキストエディターに以下の内容を入力し、必要に応じて出力先のパスなどを変更してから、「chmod」コマンドなどで実行権限を与えて動作を確認してほしい。

 #!/bin/bash

 IFS_BACKUP=$IFS
 IFS=$'\n'
 CMDNAME=`basename $0`
 DAY=`date +%Y%m%d`
 TMPDIR=/tmp/tmp`date '+%s'`

 function usage() {
    echo "Usage: $CMDNAME [対象ディレクトリ]"
    echo ""
    exit 1
 }

 if [ $# -ne 0 ] && [ -d $1 ]; then
    mkdir $TMPDIR
    find $1 -mtime -7 -type f \( -name '*.txt' -or -name '*.docx' -or -name '*.xlsx' \) \
        | xargs -i cp -v {} $TMPDIR
    genisoimage -r -J -input-charset=utf-8 -V $DAY -o $DAY.iso $TMPDIR
    rm -rf $TMPDIR
 else
    usage
 fi

 IFS=$IFS_BACKUP

本シェルプログラムを実行すると、findコマンドで1週間内に変更を加えたファイル(拡張子「.txt」「.docx」「.xlsx」)をピックアップし、それらを一時フォルダー(ディレクトリ)にコピーしてから、genisoimageコマンドでISOファイルを作成する。

シェルスクリプトを実行した状態。今回は分かりやすくするため、cpコマンドの実行結果を出力させている

カレントフォルダーに出力したISOファイルをWindows 10でマウントした状態

それではシェルスクリプトの内容を解説しよう。まず6行目ではISOファイル名やISOイメージのボリュームラベルに用いる文字列をdateコマンドで取得し、変数DAYに代入している。7行目は作業用フォルダーを作成するため、UNIX時間(エポックタイム)を使用した。具体的には1970-01-01 00:00:00 UTCからの秒数を取得し、「/tmp/tmpXXXXXXXX」というフォルダー名を取得できる。こちらを16行目のmkdirコマンドで作成し、ISOファイル用の作業フォルダーとした。

18行目ではfindコマンドの結果を、標準入力から受け取った内容を引数で指定したコマンドを実行するxargsに渡している。cpコマンドに関する説明は不要と思われるが、今回はコピー結果を示すため、オプション「-v」を追加した。冗長に感じる場合は削除して構わない。

19行目はISOファイルを作成する骨子の部分。オプション「-r」はファイル名の制限を抑えるRock Ridge形式の指定、オプション「-J」はMicrosoftのISO 9660拡張規格であるJoliet形式の指定を行っている。また、オプション「-input-charset」は文字コードを指定しているが、省略した場合はロケールから自動判断するので、場合によっては取り除いて構わない。オプション「-V」はボリュームラベル名、オプション「-o」は出力するISOファイル名を指定し、最後の引数で内容となるフォルダーを指定する。ISOファイル作成後は20行目のrmコマンドで一時フォルダーを削除して処理完了だ。

阿久津良和(Cactus)