ラベル script の投稿を表示しています。 すべての投稿を表示
ラベル script の投稿を表示しています。 すべての投稿を表示

2011年8月15日月曜日

バッチファイルに潜む罠(4) - 改行を含む文字列の Echo その2

サーカムフレックス「^」で改行をエスケープした複数行の文字列の一行目を消そうとして More +1 したら、一行も出力されない。。。

Command Prompt
C:\>type newline.cmd
@Echo Off
Set STR=^

Some string including^

newline.
Setlocal ENABLEDELAYEDEXPANSION
Echo.!STR! | More +1
Endlocal

C:\>newline.cmd


C:\>

ファイルへリダイレクトして確認したら、サーカムフレックス「^」でエスケープした改行は CRLF ではなくて LF。。。

Set 変数 | (command) を使うと……

Command Prompt
C:\>type newline.cmd
@Echo Off
Set STR=^

Some string including^

newline.
Set STR | More +1

C:\>newline.cmd
Some string including
newline.


C:\>

……成功するから、ほかのコマンドにリダイレクトするときは、バッチファイルでも遅延評価を使わないで
Set 変数名 | (command)
がいいみたい。

バッチファイルに潜む罠(3) - 改行を含む文字列の Echo

改行を含んだ文字列を Echo するには、改行をサーカムフレックスで「^」でエスケープすればよくて、

Command Prompt
C:\>echo. Some string including^
More?
More? newline.
 Some string including
newline.

C:\>

Set コマンドもうまくいく。

Command Prompt
C:\>Set STR=Some string including^
More?
More? newline.

C:\>Set STR
STR=Some string including
newline.

C:\>

でも、Set した変数を Echo すると……

Command Prompt
C:\>Echo.%STR%
Some string including

C:\>

1行目しか表示されない。遅延評価じゃないから 1行目しか表示されないのは分かるけど、2行目の newline. がエラーにならないので、デバッグしにくい。

対処

バッチファイルなら遅延評価(!変数!)が使えるけれど……

Command Prompt
C:\>type newline.cmd
@Echo Off
Set STR=Some string including^

newline.
Setlocal ENABLEDELAYEDEXPANSION
Echo.!STR!
Endlocal

C:\>newline.cmd
Some string including
newline.

C:\>

……コマンドプロンプトでは Setlocal が使えない。

とりあえず 1行目に余分な改行を追加して、使うとき More +1 で 1行目を削除でしのぐ。

Command Prompt
C:\>Set STR=^
More?
More? Some string including^
More?
More? newline.

C:\>Set STR | More +1
Some string including
newline.


C:\>

続き

2011年8月14日日曜日

バッチファイルに潜む罠(2) - Call :(label) の出力を他のコマンドにリダイレクトすると失敗する。

ファイルへのリダイレクトは問題ないけど……

Command Prompt
C:\>dir /b *.txt
aaa.txt
bbb.txt
ccc.txt

C:\>type call2file.cmd
@Echo Off

Call :ECHO_ARGS %*> args.log
Exit /B 0

:ECHO_ARGS
For %%i In (%*) Do Echo.%%~i
Exit /B 0

C:\>call2file.cmd *.txt

C:\>type args.log
aaa.txt
bbb.txt
ccc.txt

C:\>

コマンドへリダイレクトすると……

Command Prompt
C:\>type call2cmd.cmd
@Echo Off

Call :ECHO_ARGS %*| More
Exit /B 0

:ECHO_ARGS
For %%i In (%*) Do Echo.%%~i
Exit /B 0

C:\>call2cmd.cmd
バッチ スクリプト外でバッチ ラベルを呼び出すことはできません。


C:\>

失敗。。。

対処

考え中……

バッチファイルに潜む罠(1) - シェルはファイル名展開してくれない。

Command Prompt
C:\>dir /b *.txt
aaa.txt
bbb.txt
ccc.txt

C:\>type expansion.cmd
@Echo.%*

C:\>expansion.cmd *.txt
*.txt

C:\>

対処

For 文のファイル名展開機能を使う

Command Prompt
C:\>type expansion.cmd
@For %%i In (%*) Do @Echo.%%i

C:\>expansion.cmd *.txt
aaa.txt
bbb.txt
ccc.txt

C:\>

2011年8月12日金曜日

バッチファイルで which コマンド

which.cmd
@Echo Off
If "%1"=="" (
  Echo.Usage: %~nx0 COMMAND
  Echo.Write the full path of COMMAND^(s^) to standard output.
  Exit /b 0
)

For %%i In (%PATHEXT%) Do Call :EXIST_THEN_ECHO %1%%i && Exit /b 0
Echo.%~nx0: no %1 in (%PATH%)
Exit /b 1

:EXIST_THEN_ECHO
If Not Exist "%~1\" If Exist "%~1" Echo..\%~1& Exit /b 0
If Not "%~$PATH:1"=="" Echo.%~$PATH:1& Exit /b 0
Exit /b 1

IE8 や Firefox3 などの data スキーマに対応しているブラウザなら

参照

  • help call

修正履歴

  • カレントフォルダを先に確認 (2011.08.15)
    :EXIST_THEN_ECHO
    If Not "%~$PATH:1"=="" Echo.%~$PATH:1& Exit /b 0
    If Not Exist "%~1\" If Exist "%~1" Echo..\%~1& Exit /b 0

    :EXIST_THEN_ECHO
    If Not Exist "%~1\" If Exist "%~1" Echo..\%~1& Exit /b 0
    If Not "%~$PATH:1"=="" Echo.%~$PATH:1& Exit /b 0

指定されたパスがフォルダか否か調べる(コマンドプロンプト/バッチファイル) - その 2

If Exist でパス名の最後に「\」をつける。

Command Prompt
C:\>type nul > file

C:\>mkdir folder

C:\>If Exist folder\ (Echo.Folder.) Else (Echo.Not folder.)
Folder.

C:\>If Exist file\ (Echo.Folder.) Else (Echo.Not folder.)
Not folder.

C:\>

確認

  • Windows XP Professional Service Pack 3

2011年8月9日火曜日

指定されたパスがフォルダか否か調べる(コマンドプロンプト/バッチファイル)

Command Prompt
C:\>Type nul>file

C:\>Mkdir folder

C:\>dir /ad file.txt>nul 2>&1 || Echo.file is not folder.
file is not folder.

C:\>dir /ad /b folder>nul 2>&1 && Echo.folder is folder.
folder is folder.

C:\>

続き

2011年8月8日月曜日

WScript でパスワードを入力させる

バッチファイルからパスワードを入力させる方法を探して PowerShell に行き着いたけれど、WScript でできる(※参照)みたいなので PowerShell はまたしばらくお休み。

コマンドプロンプト
C:\>type password.vbs
WScript.StdOut.Write "Password: "
strPassword = CreateObject("ScriptPW.Password").GetPassword()
WScript.Echo
WScript.Echo strPassword

C:\>CScript //Nologo password.vbs
Password:
password

C:\>

注意

[ScriptPW.Password] は Windows XP から。Windows 2000 は使用不可(※参照)。

確認

  • Windows XP Service Pack 3
  • Microsoft (R) Windows Script Host Version 5.7

参照

2011年8月4日木曜日

PowerShell メモ

  • コマンドプロンプト(or バッチファイル)からコマンドを指定して実行
    C:\> powershell -Command コマンド群
    ※ クォートやエスケープはいらない。
    ※ 複数のコマンドは ";" で分割
  • コマンドプロンプト(or バッチファイル)からスクリプトを呼び出す
    C:\> powershell -ExcecutionPolicy RemoteSigned -File スクリプト.ps1
  • パスワードを入力させる
    PS> $password = read-host Password -AsSecureString Password: 123456789 PS> $password System.Security.SecureString
    ※ 直接文字列は取得できない
  • [System.Security.SecureString] から文字列を取得する
    PS> $ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($password) PS> [Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr) 123456789

参照

  • ユーザに文字列を入力させる(1)/(2) - PowerShell Memo
    → http://d.hatena.ne.jp/newpops/20050922/p1
    → http://d.hatena.ne.jp/newpops/20050923/p1

2011年8月2日火曜日

応答があるまで ping を繰り返すバッチファイル

実行方法

  • コマンドプロンプトから引数にホスト名か IP アドレスを指定する。
  • 名前がホスト名か IP アドレスのファイルをバッチファイルにドラッグする。
loop_ping_til_reply.cmd
@Echo Off
Rem (c) http://sofnote.blogspot.com/

Set WAITTIME=60
Set CMDNAME=%~nx0
Set TARGET=%~nx1
If Not "%TARGET%"=="" Goto ARGS_OK
  Echo.Usage:
  Echo.  %CMDNAME% (hostname ^| ip address)
  Echo.or
  Echo.  drag [(hostname ^| ip address)] file icon to [%CMDNAME%] icon.
  Goto ERROR
:ARGS_OK

Rem hostname check
Echo.executing: ping -n 1 %TARGET%...
Set LINES=0
For /F "tokens=*" %%i In ('ping -n 1 %TARGET%') Do Call :PING_ERR_CHECK ".%%i"
  If Not %LINES%==1 Goto HOSTNAME_OK
  Goto ERROR
:HOSTNAME_OK
If %LINES%==9 Goto SUCCESS
ping localhost -n %WAITTIME% > nul

:RETRY
  Echo.executing: ping -n 1 %TARGET%...
  ping  -n 1 %TARGET%
  if Not ERRORLEVEL 1 Goto PINGABLE
  ping localhost -n %WAITTIME% > nul
  Goto RETRY
:PINGABLE


:SUCCESS
Pause
Exit /b 0

:ERROR
Pause
Exit /b 1

Rem Return values:
Rem   LINES: number of line which ping result
:PING_ERR_CHECK
Setlocal ENABLEDELAYEDEXPANSION
  Set MSG=%1
  For /F "tokens=*" %%i In (!MSG!) Do Echo%%~i
Endlocal
Set /A LINES=%LINES%+1
Exit /b 0

IE8 や Firefox3 などの data スキーマに対応しているブラウザなら

2010年3月8日月曜日

gnome デスクトップ - ダブルクリックで実行したときの変数

/tmp/test/$PWD.sh
#!/bin/sh echo $PWD read -n 1 -p "any key for exit" i
結果
/tmp/test any key for exit
/tmp/test/$0.sh
#!/bin/sh echo "$0" read -n 1 -p "any key for exit" i
結果
/tmp/test/$0.sh any key for exit

シェルスクリプト/バッチファイルで一時停止

シェルスクリプト

bash
$ echo -n "any key for exit"; stty -echo; read -n 1 i; stty echo; echo
any key for exit
$ 

下記 shell で確認

  • bash(sh で起動)
    GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)
  • ksh
    sh (AT&T Research) 93s+ 2008-01-31

バッチファイル

Command Prompt
>pause
続行するには何かキーを押してください . . .

>

下記 shell で確認

  • cmd.exe
    Microsoft Windows XP [Version 5.1.2600]

2010年3月7日日曜日

シェルスクリプト/バッチファイルでフルパス名を分割

シェルスクリプト

フルパス名からファイル名部分を取り出す

bash
$ echo $PWD
/usr/local/lib/firefox-3.6
$ echo ${PWD##*/}
firefox-3.6
$ 

※ 先頭の最長一致部分を削除

フルパス名からディレクトリ名を取り出す

bash
$ echo ${PWD%/*}
/usr/local/lib
$ 

※ 末尾の最短一致部分を削除

下記 shell で確認

  • bash(sh で起動)
    GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)
  • ksh
    sh (AT&T Research) 93s+ 2008-01-31

バッチファイル(cmd.exe)

フルパス名からファイル名部分を取り出す

Command Prompt
>echo %CD%
C:\WINDOWS\system32\drivers\etc
>for %i in ("%CD%") do @echo %~ni%~xi
etc

>

※ ~n:ファイル名(拡張子を除く)
※ ~x:拡張子

フルパス名からディレクトリ名を取り出す

Command Prompt
>for %i in ("%CD%") do @echo %~di%~pi
C:\WINDOWS\system32\drivers\

>

※ ~d:ドライブ名を展開
※ ~p:パス名を展開

下記 shell で確認

  • cmd.exe
    Microsoft Windows XP [Version 5.1.2600]