Seleniumでダウンロード先ディレクトリを指定する

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument("--incognito")
options.add_preference "download.default_directory", "D:/Work/Down"
options.add_preference "download.prompt_for_download", false

driver = Selenium::WebDriver.for :chrome, options: options

では駄目で、ダウンロードがエラーになった。 ディレクトリはバックスラッシュで指定する必要がある。解釈をRubyじゃなくてChromeがするからだろう。

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument("--incognito")
options.add_preference "download.default_directory", 'D:\Work\Down'
options.add_preference "download.prompt_for_download", false

driver = Selenium::WebDriver.for :chrome, options: options

コマンドプロンプトの微妙な仕様

コマンドプロンプトで、aaa\..\foo.txtと入力すると、カレントディレクトリにaaaというディレクトリがあれば、その親のfoo.txtなので結局カレントディレクトリのfoo.txtが拡張子に関連付いたプログラムが起動してファイルを開くのは当然だ。

しかし、aaaが存在しなくてもエラーにならず、カレントディレクトリのfoo.txtが拡張子に関連付いたプログラムが起動する。

これは本来はエラーになるべきでは?

type aaa\..\foo.txt等も同様にエラーにならず、表示される。

追記

コマンドプロンプトだけじゃなくて、プログラムでファイルオープンする場合も同じ。"aaa\..\foo.txt"がオープンできる。

CD コマンドの機能拡張 第三版

CD コマンドの機能拡張 第二版」以来、16年ぶりの大幅修正。機能は変えていないが、リファクタリングで機能追加がシンプルになった。

cdd.batという名前で作って、doskey cd=cdd $*でaliasを定義して使う。

機能は、

  • 移動はすべて pushd で行う。
  • cd のみのときはディレクトリスタックの表示
  • ホーム(%HOME%)への移動は cd ~
  • cd - で前のディレクトリに戻る
  • cd + で現ディレクトリと一つ前のディレクトリの交換
  • cd 存在するディレクトリ だとそこへ移動
  • cd ショートカット の場合、ショートカット先がディレクトリならそこへ移動し、ファイルだとそのファイルのあるディレクトリへ移動
  • cd 存在するファイル だとそのファイルのあるディレクトリへ移動 (explorerからcmdプロンプトへファイルをドラッグ&ドロップしたとき便利)
  • cd それ以外 の場合環境変数CDPATHを探索してオペラランドがそこにディレクトリとして存在すればそこに移動

ほとんどの機能はモジュール化していて、ファイルの最後で定義する。

  • 指定文字列 移動先ディレクトリ
  • 指定文字列 サブルーチン

サブルーチンの1つとして、RubyのGemsディレクトリへの移動を書いてみた。 Firefoxのプロファイルディレクトリも、profiles.iniを読んで決めるようにしようかと思ったけど、面倒くさいわりにメリットが無いのでやめた。

@echo off
rem 定義済みの移動先ならそこに移動する
call :PreDefined "%~dpnx0" "%~1"
if not ERRORLEVEL 1 exit /b

rem 存在するディレクトリ、ファイル、ショートカットか?
rem ファイルの場合はそのディレクトリに移動する
if exist "%~1" (
  dir /b/ad "%~1" >NUL 2>NUL
  if not ERRORLEVEL 1 (
    call :Pushd "%~1"
  ) else (
    if /i "%~x1"==".lnk" (
      call :Shortcut "%~1"
      if not ERRORLEVEL 1 exit /b
    )
    call :Pushd "%~dp1"
  )
  exit /b
)

rem %CDPATH% に存在するディレクトリなら、そこに移動する
if not "%~$CDPATH:1"=="" dir /b/ad "%~$CDPATH:1" >NUL 2>NUL && (
  call :Pushd %~$CDPATH:1
  exit /b
)

:Pushd
rem 移動用処理
rem pushd が成功しても元と同じならpopdする(同じ履歴を残さないため)
for /f "delims=" %%X in ("%CD%") do (
  pushd %*
  if not ERRORLEVEL 1 for /f "delims=" %%Y in ('echo "%%CD%%"') do (
    if "%%X"=="%%~Y" popd
  )
)
exit /b

:Shortcut
rem ショートカットファイルのリンク先を調べてそこに移動する
setlocal enabledelayedexpansion
set "SV="
set "FILE="
for /f "delims=" %%A in ('more ^< "%~1"') do (
  set A=%%A
  if "!A:~1,2!"==":\" for %%B in (A B C D E F G H I J K L M N O P Q R S T U V W
     X Y Z) do if "!A:~0,1!"=="%%B" set "FILE=%%A"
  if defined SV (if defined FILE (set "FILE=!FILE!%%A")else set "FILE=!SV!\%%A")&set "SV="
  if "!A:~0,2!"=="\\" set "SV=%%A"
)
if defined FILE endlocal&call :Pushd "%FILE%"&exit /b 0
rem リンク先が見つからない場合
exit /b 1

:PreDefined
rem 定義済み移動先の処理を行う
rem 移動先ディレクトリ名 または 呼び出すサブルーチン名
setlocal enabledelayedexpansion
set "DATA="
for /f "usebackq tokens=1*" %%A in (%1) do (
  if /i "%%~A" == "__DATA__" (
    set DATA=1
  ) else if defined DATA (
    set "X=%%~B"
    if /i "%%~A" == "%~2" if "!X:~0,1!" == ":" (
      endlocal
      call %%~B %*
      exit /b 0
    ) else (
      endlocal
      call :Pushd "%%~B"
      exit /b 0
    )
    if /i "%~2" == ":Help" echo.%%A %%B
  )
)
if /i "%~2" == ":Help" exit /b 0
rem 定義済み移動先に存在しなかった
exit /b 1

rem ここから個別処理
:Dirs
rem ディレクトリスタックを横に並べて表示する
  setlocal enabledelayedexpansion
  set TEMPFILE="%TEMP:"=%\cd$$.tmp"
  pushd > %TEMPFILE%
  set "DIRS=%CD%"
  for /f "usebackq delims=" %%A in (%TEMPFILE%) do set "DIRS=!DIRS! %%~A"
  del %TEMPFILE% 2>NUL
  set /p "=%DIRS%"<NUL
  exit /b

:Back
rem 1つ前のディレクトリへ
  popd
  goto :Dirs

:Swap
rem 1つ前のディレクトリに移動して、履歴に今のディレクトリを入れる
  for /f "delims=" %%X in ('echo "%%CD%%"') do (
    popd
    for /f "delims=" %%Y in ('echo "%%CD%%"') do (
      popd
      for /f "delims=" %%Z in ('echo "%%CD%%"') do (
      if not "%%~Y"=="%%~Z" (pushd %%X) else (cd /d %%X) 
      if not "%%~X"=="%%~Y"  pushd %%Y
  )))
  goto :Dirs

:Help
rem 定義済み移動先の一覧の表示
  call :PreDefined %1 :Help
  exit /b

:RubyGems
rem RubyGemsのディレクトリへ
  for /f "tokens=1-3 delims=." %%A in ('ruby -e "puts RUBY_VERSION"') do (
    call :Pushd "D:\Ruby\lib\ruby\gems\%%A.%%B.0\gems"
  )
  exit /b

rem ここから移動先定義
__DATA__
""  :Dirs
-   :Back
+   :Swap
/?  :Help
~   %HOME%
/   %TEMP%
//  D:\Temp
/e  %windir%\system32\drivers\etc
/f  %APPDATA%\Mozilla\Firefox\Profiles\xxxxxxxx.20180101
/g  :RubyGems

スマートホームを少し始める

Amazon Echoと連携できる赤外線リモコン SwitchBot を買ってみました。

スマホアプリでコントロールすることもでき、Alexaアプリと連携することでEchoで指示できる。ただし、Echoで指示できるのは一部だけ。 寝室のPanasonicのシーリングライトとエアコンでやってみましたが、SwitchBotスマホアプリだとオンオフの他に明るさや温度調整ができるけど、Alexa/Echoだとオンとオフのみ。

シーリングライトは20年物のせいか、1回でで反応するときもあるけど、2回、3回と実行しないと反応しないこともあるので、Alexaアプリで3回実行する操作に名前を付けました。

Windows Updateでトラブル

WindowsUpdateで再起動したところ、Explorerからファイルを開こうとすると

指定されたデバイス、パス、またはファイルにアクセスできません。これらの項目にアクセスするための適切なアクセス許可がない可能性があります。

というエラーダイアログが出る。コマンドプロンプトからコマンドを明示して開くと開けるため、拡張子関連付けがおかしいと思われるので、レジストリを見てみる。

Dドライブに関して、D:\foo\barとなっているべきところが、軒並み*:\foo\barとドライブ名がアスタリスクに変わっている。 他にも拡張子関連付け自体が消えているものもある。

修正するともちろん問題ない。量が多すぎる(100以上)なので、exportしてプログラムで編集してregファイルを作ってimportした。手作業では無理。

いろいろアップデートするバッチスクリプト

MSYS、Ruby Gems、Python PIPsをアップデート。

pacman -Syu
call gem update --system
@echo on
call gem update
@echo on
for /f "skip=2" %%A in ('pip list -o') do python -m pip install -U --progress-bar off %%A