2016/09/27(火) [n年前の日記]
#1 [prog] VBScriptを少し勉強
Windows上でPerl(ActivePerl)を使ってファイル操作をする場合、日本語ファイル/ディレクトリ名に対してハマる時があるなと感じたわけだけど。
どうせ Windows上でしか使わないスクリプトであれば、いっそ WSH だか VBScript あたりで書いたほうがいいのかもしれないなと思えてきて。てなわけで、VBScript を少し勉強。
例えば、2つのディレクトリのパスを指定すると、中に入ってるディレクトリ名一覧を取得して同名が無いか比較するVBScriptを書いてみたりして。
_dircmp_double.vbs
「今頃VBScriptかよ」「せめて百歩譲ってもPowerShellじゃねえの」と笑われそうな気もするけど、PowerShellでスクリプトを書くと実行ポリシーの問題が出てくるから個人的に面倒臭い…。PowerShellスクリプトを実行可能状態に設定するには管理者権限でPowerShell開いてから特定コマンドを打たないといけないので、プログラマーの類ならともかく万人が使えるソレなのですか、どの環境でもそのスクリプトが動くのですかと考えるとビミョーだし。 *1 、あるいは一旦batファイル等を経由すればそのあたりの設定を省略できるかもしれんけどスクリプトと一緒にbatファイルがついて回るのもなんだかダサいし。 *2 そもそも、この程度の処理に「PowerShell使うべき」と言い始めちゃうのもなんだか大袈裟だよなと。
つーかこの程度のソレなら何使っても書けるだろうから何でもいいよな。Perlは論外としても、達人なら batファイルで同じ処理を書いちゃったりするかもしれん。
どうせ Windows上でしか使わないスクリプトであれば、いっそ WSH だか VBScript あたりで書いたほうがいいのかもしれないなと思えてきて。てなわけで、VBScript を少し勉強。
例えば、2つのディレクトリのパスを指定すると、中に入ってるディレクトリ名一覧を取得して同名が無いか比較するVBScriptを書いてみたりして。
_dircmp_double.vbs
' 重複ディレクトリ名を一覧表示するVBScript ' ' 2つのディレクトリパスを渡して、 ' サブディレクトリ名を取得後に比較して重複を探す。 ' 同じディレクトリ名が存在したらリストアップする。 ' ' usage : wscript dircmp_double.vbs DIR1 DIR2 Option Explicit ' 引数を取得 Dim argv Set argv = WScript.Arguments If argv.Count <> 2 Then MsgBox "引数の数が違います。" & vbCrLf & vbCrLf & _ "usage: wscript " & WScript.ScriptName & " DIR1 DIR2", _ vbOKOnly + vbCritical, "Error" WScript.Quit End If Dim fso, f1, f2, d1, d2, c Dim s ' サブフォルダ一覧を取得 set fso = createObject("Scripting.FileSystemObject") set f1 = fso.getFolder(argv(0)) set f2 = fso.getFolder(argv(1)) ' フォルダ名を比較して同名が見つかったら文字列変数に記録 s = "" c = 0 For Each d1 in f1.subfolders For Each d2 in f2.subfolders If StrComp(d1.Name, d2.Name, 1) = 0 Then s = s & d2.Name & vbCrLf c = c + 1 End If Next Next ' 結果表示 If c = 0 Then s = "重複ディレクトリ名はありません。" End If MsgBox s, vbOKOnly, "比較結果"
「今頃VBScriptかよ」「せめて百歩譲ってもPowerShellじゃねえの」と笑われそうな気もするけど、PowerShellでスクリプトを書くと実行ポリシーの問題が出てくるから個人的に面倒臭い…。PowerShellスクリプトを実行可能状態に設定するには管理者権限でPowerShell開いてから特定コマンドを打たないといけないので、プログラマーの類ならともかく万人が使えるソレなのですか、どの環境でもそのスクリプトが動くのですかと考えるとビミョーだし。 *1 、あるいは一旦batファイル等を経由すればそのあたりの設定を省略できるかもしれんけどスクリプトと一緒にbatファイルがついて回るのもなんだかダサいし。 *2 そもそも、この程度の処理に「PowerShell使うべき」と言い始めちゃうのもなんだか大袈裟だよなと。
つーかこの程度のソレなら何使っても書けるだろうから何でもいいよな。Perlは論外としても、達人なら batファイルで同じ処理を書いちゃったりするかもしれん。
◎ Rubyで書いた場合。 :
ちなみに Ruby で書いたらこんな感じに。
_dircmp_double.rb
_dircmp_double.rb
#!ruby -Ks # 2つのディレクトリパスを渡して、サブディレクトリ名を取得後、比較。 # 同じディレクトリ名が存在したらリストアップする。 # # usage : ruby dircmp_double.rb dir1 dir2 require "io/console" $dbg = false def usage puts "usage : ruby #{File.basename(__FILE__)} dir1 dir2" puts " 2つのディレクトリパスを渡して、サブディレクトリ名を取得後に比較。" puts " 同じディレクトリ名が存在したらリストアップする。" push_any_key end def push_any_key puts "\nPush Any Key" STDIN.getch exit end def get_filelist(path) puts "Search [#{path}]" flist = [] Dir::entries(path).each do |f| next if f =~ /^\.{1,2}$/ dirpath = path + "\\" + f if FileTest.directory?(dirpath) puts "[Dir] #{f}" if $dbg flist.push(f) elsif FileTest.file?(dirpath) puts "[File] #{f}" if $dbg else puts "[Unknown] #{f}" end end puts " ... #{flist.length}" return flist end if ARGV.length != 2 puts "引数の数が違います。" ARGV.each do |s| puts "[#{s}]" end usage end dirs = [] ARGV.each do |f| if FileTest.directory?(f) puts "[BaseDir] #{f}" if $dbg dirs.push(f) else puts "#{f} はディレクトリではありません" usage end end a = get_filelist(dirs[0]) b = get_filelist(dirs[1]) duplist = [] a.each do |sa| b.each do |sb| duplist.push(sa) if sa == sb end end puts if duplist.length == 0 puts "重複ディレクトリ名は見つかりませんでした。" else puts "重複ディレクトリ名 : " puts '-' * 40 duplist.sort.each do |s| puts " #{s}" end end push_any_key
◎ PowerShell関係のソレをメモ。 :
_管理者権限なしでPowerShellスクリプトを実行する方法 - Qiita
_コマンドプロンプトからPowerShellに乗り換えるための小さな本 - Qiita
_Tech TIPS:WindowsでPowerShellスクリプトの実行セキュリティポリシーを変更する - @IT
_コマンドプロンプトからPowerShellに乗り換えるための小さな本 - Qiita
_Tech TIPS:WindowsでPowerShellスクリプトの実行セキュリティポリシーを変更する - @IT
[ ツッコむ ]
以上です。