†REXXのどろぬま†

ドライブの空き容量の取得

作成開始日 2015.05.11
最終更新日 2015.05.26

REXXではSysDriveInfoを使うのが一般的。 しかし、これをUSBドライブに使うと、やたらとハングする。 なので、DIRコマンドの出力をパイプで取り込むことにした。 これは以前PIPEのサンプルとして作ったスクリプトとほぼ同じもの。 ただし、今回はドライブにメディアが刺さっていない可能性があり、 その場合のエラー処理が問題になる。

まずはメイン側のルーチンから見ていくと;

/* DIRコマンドを実行して結果をパイプに入れる */
'@DIR' DRV'\* 2>NUL | D:\BIN\PIPEDIR'
PARSE PULL st

/* 取得した空き容量情報を見やすいように加工・表示 */
fMem=WORD(st,1)
IF POS('K',st)<>0 THEN fMem=fMem*1000	/* 容量が大きいとKB単位で表示される */
IF fMem<>'NotReady' THEN fMem=MemUnit(fMem)
SAY ' ' DRV fMem
ここで; で、肝腎なのはPIPEDIR.CMDの中味。
blankLine=0

Do Forever
  PARSE PULL st
  /* 空き容量表示行を検出 */
  IF POS('バイト空き',st)>0 THEN LEAVE;

  /* 2連続ブランク行を検出 */
  IF st=''  then blankLine=blankLine+1;
  IF st<>'' then blankLine=0;
  IF blankLine=2 then
  Do
    st='NotReady'
    Leave;
  End
End
QUEUE st
ポイントは、ドライブがnot ready状態のときの判別。 not readyの場合、DIRコマンド自体は何も出力しない。 システムのエラーメッセージ(SYS0021)は出力されるが、 それをPIPEDIR.CMDの中で検出する方法は判らなかった(rcでは不可)。 従って、直接的にnot ready状態を検知することはできない。

ならば「DIRの出力がない=not ready」と考えれば良いのだが、 今度は「DIRの出力がない」ことの判別が難しい。 前述の通り、このスクリプトの中のパイプは、 たとえコマンドからの出力がなくても、永遠にブランク行を出力し続ける。 しかも、DIRコマンドの正常な出力の途中にもブランク行は存在する。 これでは、出力がないから(終了したから)ブランク行なのか、 あるいは正当な出力の途中のブランク行なのか区別が付かない。

ただし、DIRの正常出力の途中にブランク行が2行続けて現れることはない。 そこで、「2連続ブランク行=出力の終了」と考え、 それが出現するまでに「バイト空き」文字列が出てくれば正常、 いきなり2連続ブランク行が出てくればnot readyと判断することにした。

●DIRUSB.CMD

/* DIRUSB.CMD 2015.05.11 */
/* USBドライブのチェック */
Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
Call SysLoadFuncs
NUMERIC DIGITS 14	/* 有効桁数14桁      */

drvSt ='JKLM'
red   ='1B'x'[31;1m'
cyan  ='1B'x'[36;1m'
yellow='1B'x'[33;1m'
white ='1B'x'[37;1m'

SAY white
Do n=1 to 4
  drv=SUBSTR(drvSt,n,1)':'
  '@DIR' drv'\* 2>NUL | D:\BIN\PIPEDIR'		/* PIPEDIR.CMDはD:\BINに置く */
  PARSE PULL st

  fMem=WORD(st,1)
  IF POS('K',st)<>0 THEN fMem=fMem*1000
  IF fMem='NotReady'
  THEN fMem=red||fmem||white
  ELSE fMem=cyan||MemUnit(fMem)||white||' free'
  SAY ' ' DRV fMEM
END
Exit;

/*-----------------------------------------------------------------------*/
MemUnit: Procedure ;
  mem=ARG(1)
  unitSt='KMGT'
  Do m=1 to 4
     mem=mem/1000
     IF mem<1 THEN LEAVE
  End

  mem=mem*1000
  mem=LEFT(mem,3)
  IF RIGHT(mem,1)='.' THEN mem=' 'left(mem,2)

  IF m=1
  THEN mem=mem' B'
  ELSE mem=left(mem,3)||' '||substr(unitSt,m-1,1)||'B'
  Return mem
End;

●PIPEDIR.CMD(D:\BINに置く)

/* PIPE.CMD 2015.05.11 */
/* DIRコマンドの出力を受け取って、空き容量を表示する行のみをキューに送る */

blankLine=0

Do Forever
  PARSE PULL st
  IF POS('バイト空き',st)>0 THEN LEAVE;

  IF st=''  THEN blankLine=blankLine+1;
  IF st<>'' THEN blankLine=0;
  IF blankLine=2 THEN
  Do
    st='NotReady'
    blankLine=0
    Leave;
  End
End
QUEUE st


【REXXのどろぬま目次】 【ホーム】