<< NEW | main | OLD>>
バッチファイルにファイルをドラッグ&ドロップすると
そのファイルのパスを引数として取得することができますが、
パスに特殊な記号などが入っていたりすると
一つの引数の途中で勝手に文字列が分割されてしまったり、
あるいはメタ文字が消えてしまったりでうまく受け取ることができません

何かいい方法はないかと調べていると
渡された引数を解析して環境変数に詰め直すサンプルを見つけました
http://skypher.com/index.php/2010/08/17/batch-command-line-arguments/

ただリンク先で公開されているサンプルのままだと
キャレット'^'や感嘆符'!'には対応できなかったので、
とりあえずパスに含めることができる記号について
対応できるよう少し手を入れてみました


@ECHO OFF
SET ARGV=%*

SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
CALL :PARSE_ARGV
IF ERRORLEVEL 1 (
ECHO Cannot parse arguments
ENDLOCAL
EXIT /B 1
)

REM メイン処理
FOR /L %%i IN (1,1,!ARGC!) DO (
ECHO !ARG%%i!
ECHO !ARG%%i_!
ECHO !ARG%%iQ!
)

ENDLOCAL
PAUSE
EXIT /B 0

:PARSE_ARGV
SET ARGV=.!ARGV!
SET PARSE_ARGV_ARG=[]
SET PARSE_ARGV_END=FALSE
SET PARSE_ARGV_INSIDE_QUOTES=FALSE
SET /A ARGC = 0
SET /A PARSE_ARGV_INDEX=1

:PARSE_ARGV_LOOP
REM 引数の文字列を先頭から1文字ずつチェックする
CALL :PARSE_ARGV_CHAR !PARSE_ARGV_INDEX! "%%ARGV:~!PARSE_ARGV_INDEX!,1%%"
IF ERRORLEVEL 1 (
EXIT /B 1
)
IF !PARSE_ARGV_END! == TRUE (
EXIT /B 0
)
SET /A PARSE_ARGV_INDEX=!PARSE_ARGV_INDEX! + 1
GOTO :PARSE_ARGV_LOOP

:PARSE_ARGV_CHAR
REM ダブルクォート開始終了判定
IF ^%~2 == ^" (
SET PARSE_ARGV_END=FALSE
SET PARSE_ARGV_ARG=.!PARSE_ARGV_ARG:~1,-1!^".
IF !PARSE_ARGV_INSIDE_QUOTES! == TRUE (
SET PARSE_ARGV_INSIDE_QUOTES=FALSE
) ELSE (
SET PARSE_ARGV_INSIDE_QUOTES=TRUE
)
EXIT /B 0
)

REM 要エスケープ文字をバッファに追加
IF ^%~2 == ^! (
SET PARSE_ARGV_ARG=[!PARSE_ARGV_ARG:~1,-1!^^!]
EXIT /B 0
) ELSE IF ^%~2 == ^) (
SET PARSE_ARGV_ARG=[!PARSE_ARGV_ARG:~1,-1!^)]
EXIT /B 0
) ELSE IF ^%~2 == ^^ (
SET PARSE_ARGV_ARG=[!PARSE_ARGV_ARG:~1,-1!^^^^]
EXIT /B 0
)

IF %2 == "" (
REM 終了判定
REM IF !PARSE_ARGV_INSIDE_QUOTES! == TRUE (
REM REM ダブルクォートを閉じずに終了したらエラー
REM EXIT /B 1
REM )
SET PARSE_ARGV_END=TRUE
) ELSE IF NOT "%~2!PARSE_ARGV_INSIDE_QUOTES!" == " FALSE" (
REM 通常文字をバッファに追加
SET PARSE_ARGV_ARG=[!PARSE_ARGV_ARG:~1,-1!%~2]
EXIT /B 0
)

REM ダブルクォートの外でスペースがきたら引数の区切りと判断
IF NOT !PARSE_ARGV_INDEX! == 1 (
SET /A ARGC = !ARGC! + 1
SET ARG!ARGC!=!PARSE_ARGV_ARG:~1,-1!
IF ^%PARSE_ARGV_ARG:~1,1% == ^" (
SET ARG!ARGC!_=!PARSE_ARGV_ARG:~2,-2!
SET ARG!ARGC!Q=!PARSE_ARGV_ARG:~1,-1!
) ELSE (
SET ARG!ARGC!_=!PARSE_ARGV_ARG:~1,-1!
SET ARG!ARGC!Q="!PARSE_ARGV_ARG:~1,-1!"
)
SET PARSE_ARGV_ARG=[]
SET PARSE_ARGV_INSIDE_QUOTES=FALSE
)
EXIT /B 0

概要:
特殊な記号を含む引数を、記号を維持したまま環境変数に格納します
引数として想定しているのは、ファイルのドラッグ&ドロップによって与えられるパス文字列です
引数は複数存在しても大丈夫です


使い方:
冒頭で引数全体をARGVに格納してPARSE_ARGVをCALLすると
メイン処理から以下の変数経由で引数を参照できるようになります

!ARGC! - 引数の数
!ARGx! - x番目の引数
!ARGx_! - x番目の引数(ダブルクォーテーションなし)
!ARGxQ! - x番目の引数(ダブルクォーテーションあり)


制限事項など:
・ファイルに含むことができない記号('"'とか'>'とか)は面倒すぎるので考慮してません
・パスが半角スペースを含まない場合キャレット'^'が削除されます(*1)
・動作確認はWindows7 Ultimate 64bit SP1で行ないました


コード解説:
まず冒頭でARGVに引数全体を一つの文字列として格納します
注意点として、遅延展開を有効にする前にSETしておかないと
感嘆符などのメタ文字が消失してしまいます
また以降、変数を参照する際にも、
普通に%VAR%とやるといくつかの記号が影響を受けるため、
基本的には!VAR!のように遅延展開を使用します

そしてPARSE_ARGVへ飛んで解析処理に入ります
やってることはそんなに難しくなく、
ARGVから一文字ずつ取り出して解析しているだけです

最初にやっているのはダブルクォートの検出です
ダブルクォートが出現するたびに、
現在ダブルクォートの内側にいるのか外側にいるのかを
あらわすフラグを切り替えます

続いてエスケープが必要な文字を処理します
処理の流れ的にはいまひとつスマートじゃないんですが、
これらの文字は放っておくとあちこちでエラーを起こすので
早い段階で処理して早々にEXITさせてます
なぜか閉じカッコ')'は必要なキャレットの数が違いました
バッチの構文解析がカオスすぎるので深く考えたら負けだと思います

次の終了判定は特に問題はないでしょう
一点補足しておくと、元のコードではダブルクォートが閉じられなかった場合は
エラー扱いだったのですが、バッチの仕様的にはアリなので一応コメントアウトしました

その下のELSE IF NOTの条件判定はややトリッキーですが、
要するにダブルクォート外で半角スペースがくる場合以外は
通常の文字ですよーってことです
ダブルクォート外で半角スペースがくるのは引数の区切りですからね

引数の区切りに来たら、最後の部分まで処理が進み
そこでバッファの内容を変数に格納します
あとは引数文字列が終わるまで同じ事を繰り返します


--

と、ドヤ顔で書いてますが、
ほんのちょっと手入れるはずがえらい時間かかりました…
大体バッチは機能が貧弱な上にあらゆるところで仕様が糞すぎです
FOR文とか頭おかしいとしか思えません

今後は、FORとかIFとか使うレベルの処理が必要になったら
問答無用でWSHとかで作りなおすことにしようと思います
今回はホント無駄に疲れましたorz



*1)
パスが半角スペースを含んでいる場合、引数は自動的にダブルクォートで囲まれた状態で入ってくるのですが、
半角スペースを含まない場合は囲んでくれないというふざけた仕様により、キャレットがメタ文字として解釈されてしまうためです。
冒頭でecho %*とやった時点ですでに削除されているのでどう頑張っても取得出来ないと思われます。
Windows/.NET comments(0) -


コメント


フォーム

ブログ内検索

自作ツールなど
■棒読みちゃんプラグイン
2ch専用ブラウザ読み上げ(改良版)

■IntelliPark設定ツール
WDIDLE3 for Windows

■マウスユーティリティ
Wheelpool

■ユーザー入力監視ソフト
iDLEM@STER

■さぽている攻略 [公開終了]
さぽつ~る(さぽつーる)
アイテムリスト成型
調合成功率計算
カテゴリー別

openclose

プロフィール

Author:百合亞
敬虔な百合信仰者かつ崇拝者
将来の夢は女の子

管理人にメール

お名前:
メール:
件 名:

りんく
「天結いキャッスルマイスター」応援中!

『想いを捧げる乙女のメロディー』2017年3月24日発売予定

オトメ*ドメイン

eye★phon(アイ・フォン)『つい・ゆり ~おかあさんにはナイショだよ~』

AXL新作第12弾「恋する乙女と守護の楯~薔薇の聖母~」 2016年1月29日発売予定!

お嬢様と秘密の乙女

カミツレ

FLOWERS

2014年発売予定のNavel新作『月に寄りそう乙女の作法2』を応援しています!

【ハピメア】応援バナー

【白雪の騎士】応援バナー

ノブレスオブルージュ

2013年発売予定のNavel新作『乙女理論とその周辺』を応援しています!

シロガネオトメ

『ヒメゴト・マスカレイド』応援中!

2012.10.26発売のNavel新作『月に寄りそう乙女の作法』を応援しています!

屋上の百合霊さん

天使の羽根を踏まないでっ

「キミとボクとエデンの林檎」公式サイトへ

『るいは智を呼ぶファンディスク』を応援しています!

『処女はお姉さまに恋してる ~2人のエルダー~』絶賛発売中!!

りんく2
藤真拓哉オフィシャルブログ
CrystalDiskInfo - 水晶雫

マリかう

Powered by FC2 Blog    Templete by hacca*days.

PR