書庫ファイルに含まれる複数のオーディオファイルを一時ディレクトリに展開して再生する
「複数のオーディオファイルをまとめたファイルをマウントして再生する(無圧縮tarボールを推奨)」の最後で触れたのだが、書庫ファイルに含まれる複数のオーディオファイルの再生は、一時ディレクトリに展開して処理するのが(うまくはないが)手っ取り早いため、前回のシェルスクリプトをベースにしてそのように修正してみた。
[任意]ファイル名: play-archive-tmp.sh
#! /bin/bash shopt -s extglob # case ## players PLAYERS=(audacious totem) ## default PLAYER_NO=0 TMPDIR=/dev/shm #TMPDIR=/tmp usage() { local x i=0 local players_list_str="" # 0:player1|1:player2|2:player3... for x in ${PLAYERS[*]}; do players_list_str=${players_list_str}$(printf "|%d:%s" ${i} ${x}) i=$((${i} + 1)) done printf "Usage: %s [-h] [-m MOUNTPOINT] [-p PLAYER] [-w] [-z] archivefile -h print help -p PLAYER use PLAYER (%s) -z use Zenity file selection dialog\n" $(basename $0) ${MOUNTPOINT} ${players_list_str/|/} >&2 } die() { echo "ERROR: "$1 >&2 exit 1 } USE_ZENITY=0 ARCHIVEFILE="" while getopts 'hp:z' OPT do case ${OPT} in p) PLAYER_NO=$((${OPTARG//[^0-9]/})) if [ ${PLAYER_NO} -gt $((${#PLAYERS[@]} - 1)) ]; then printf "ERROR: Illegal player number(%d) [max %d]\n" ${PLAYER_NO} $((${#PLAYERS[@]} - 1)) >&2 exit 1 fi ;; z) ARCHIVEFILE=$(zenity --file-selection) if [ $? -ne 0 ]; then exit 1; fi # cancel USE_ZENITY=1 ;; ?) usage exit 1 ;; esac done shift $((${OPTIND} - 1)) if [ ${USE_ZENITY} -eq 0 ]; then ARCHIVEFILE=$1; fi case ${ARCHIVEFILE} in *.t?(ar.)bz2) EXTRACT_CMD=tar EXTRACT_OPT=jxf ;; *.t?(ar.)gz) EXTRACT_CMD=tar EXTRACT_OPT=zxf ;; *.tar) EXTRACT_CMD=tar EXTRACT_OPT=xf ;; *.zip?(.mp3)) EXTRACT_CMD=unzip EXTRACT_OPT="" ;; *) die "unknown file type" ;; esac IFS=" " ARCHIVE_BASENAME=$(basename ${ARCHIVEFILE}) TMPDIR_ARCHIVENAME=${TMPDIR}/${ARCHIVE_BASENAME} # relative path ==> absolute path (ARCHIVEFILE) ARCHIVEFILE=$(cd $(dirname ${ARCHIVEFILE}) && pwd)/${ARCHIVE_BASENAME} # extract mkdir ${TMPDIR_ARCHIVENAME} || die "mkdir failed" cd ${TMPDIR_ARCHIVENAME} ${EXTRACT_CMD} ${EXTRACT_OPT} ${ARCHIVEFILE} >/dev/null || die "extract failed" # play ${PLAYERS[${PLAYER_NO}]} ${TMPDIR_ARCHIVENAME} || die "cannot launch ${PLAYERS[${PLAYER_NO}]}" # cleanup rm ${TMPDIR_ARCHIVENAME} -fr
処理の流れとしては
のようになり、難しくはないのだが、幾つか注意点があった。
- 展開コマンドやオプション指定は書庫の種類ごとに異なるため、拡張子で判別して決めるようにした
- bashにおけるcase文でのパターンマッチングは「パス名展開」のルールで、細かくは指定できないが、「shopt -s extglob」(拡張パターンマッチングを有効にする)指定で、「*.tar.bz2」と「*.tbz2」を「*.t?(ar.)bz2」という1つのパターンにするなどのことはできるようになる
- 作業ディレクトリを移動して展開する関係で、入力ファイルが相対パスで指定された場合は絶対パスに置き換えないと展開に失敗する。そのため、入力ファイルに対して相対パスから絶対パスへの変換処理を行った(あまり使用しないpwdコマンドが役に立った)
実用性としては、展開の時間と負荷はかかるものの、書庫ファイルのサイズがそれほど大きなものでなければarchivemountでマウントするよりもよいのではないかという気がした。メモリが十分にあれば、/dev/shm以下を使用すればディスクアクセスも減らせる。メモリに余裕がなくても、一時ディレクトリに使用するためのディスク領域があれば展開もできる(変数TMPDIRを変更する)。