Help us understand the problem. What is going on with this article?

タスクスケジューラからbatファイルを起動する際のbatファイル内のパス指定

batファイルを直接起動したときとタスクスケジューラから起動したときで挙動が違ったため、メモ

batファイルは設定ファイルの中身のデータを変数として外部ファイル(batと同階層に存在)から読み込むものとする。
このbatファイルを直接起動する場合、相対パス(ファイル名のみ)でも参照可能だったので以下の状態で設定

ファイル名表示.bat
@echo off
@chcp 65001

@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルと同階層にあること
@if not exist %SettingTxt% goto notFileEnd
::設定ファイルがない場合、最後まで飛ばす

@for /f "usebackq delims== tokens=1,2" %%i in (%SettingTxt%) do set %%i=%%j
::設定の各種情報を外部ファイルから変数に設定
::=の前を変数名、=の後を値として記憶させる(do set %%i=%%j)

@echo %TxtNames%%extendChild%
@goto finishedTask

:notFileEnd
set karyunagi="%SettingTxt%ファイル自体なかった"

:finishedTask
set /p karyunagi="操作完了"
変数設定.txt
TxtNames=拾うデータ
extendChild=.txt

本来は生成したファイル名があるかの判定とかあるが、そこは省略

しかし、タスクスケジューラから起動するとなにも実行せずに閉じる。

タスクスケジューラからbatファイルを開くところは起動しているので、bat内部でパスが指定できていないことになる。

調べたところ、タスクスケジューラから起動すると、パス位置がbatファイル位置を参照せずにファイル名をローカルディスク直下のパスとして探してしまうため、起きていたようだ。

タスクスケジューラでは・・・?

解決策を探していたら、以下のページを見つけた。

[Windows]タスクスケジューラで作業フォルダを指定する方法

タスクスケジューラ内の「開始(オプション)(I)」にbatファイルフォルダのパスを設定すると動くらしい。

実際試してみたら動いた。

・・・

いや、まぁ動いたけどこれ
batファイルの位置が固定で変化しない前提だよね・・・

普通は変更掛からないはずだけど、
事情があって変更みたいなことを考えると、絶対参照で書きたくはない

しかも、固定でない場合は変更がかかるたびに2か所もいちいち修正しなくてはならなくなるから、めんどい・・・
(ここ以外にも起動するbatファイルパスをタスクスケジューラの「プログラム/スクリプト(P):」も修正する必要がある)

bat側で指定する

よくよく考えてみたら、batのパスをbat内で指定すればいけるんじゃないかと思い、

@set pathes=%~d0
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルと同階層にあること
@set SettingTxt="%pathes%%SettingTxt%"

のように一部追加変更した。
最後の SettingTxt の "" は、
パス内に半角空白が入っていた時の対策のために入れている。半角空白があるとその先はコマンドが区切られているとして解釈し、ファイル名として読み取れなくなってしまう。



が・・・変わらない。

と思ったら、ドライブしか拾えてなかった。

d のみだとドライブしか拾えない
@set pathes=%~d0

上記の指定だと、ドライブしか指定していないため、ドライブしか参照できていない。
ファイル名を除いたパスを指定する場合、「p」も指定する必要がある。

ということで、設定ファイルのパス取得に追加

設定ファイルに dp 指定( pd でも可)
@set pathes=%~dp0
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルと同階層にあること
@set SettingTxt="%pathes%%SettingTxt%"

実行できた。

バッチ内で自パスを拾うので、疑似相対パス参照はできた。

もっとも自パスの1つ上階層内の別フォルダ指定は試してみたが、できなかった(というかできない?)ので、batのみで同一階層下以外の相対パス参照は無理っぽい?

20/08/03 追記

コメントいただいたものでpushdを用いてみたところ、相対参照もできた。

設定ファイルパスに pushd 指定、1つ上階層のtestフォルダ参照
@set pathes=%~dp0
pushd %pathes%..\test\
@set pathes=%cd%
@set SettingTxt=変数設定.txt
::設定ファイルはbatファイルの1つ上階層のtestフォルダ内にあること
@set SettingTxt="%pathes%\%SettingTxt%"

ただし、%~dp0から遡る都合か、
%~dp0時にあった最後の/は存在しなくなってしまうので、
変数結合時(最後のSettingTxt)に追加している。

参考

パス名の文字列を自在に切り取る - 知識ゼロからのwindowsバッチファイル超入門
バッチファイルでの「スペース」を含んだ文字列の取り扱い - 知識ゼロからのwindowsバッチファイル超入門
.bat(バッチファイル)のforコマンド解説。 - Qiita

sazaby-league-hr
株式会社サザビーリーグの特例子会社。横浜業務サポートセンターはITに特化した業務支援を行う拠点です。「障がい者による社会貢献」という当たり前の社会を「半歩先」に作ることを目指しています。
http://www.sazaby-league-hr.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away