みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

スクリプトの変更をお願いします

PC内のshift-jisのテキストファイルを事情により全てutf-8(BOM付)に変える必要があります。

ネットを探したところ下記サイトでbatファイルの作り方がありました。
http://www.shegolab.jp/entry/windows-conv-text-utf8

↓スクリプトの内容
@echo off
:Shift_JIS -> BOM UTF-8
setlocal enabledelayedexpansion
for %%f in (%*) do (
echo %%~ff| findstr /l /e /i ".txt .csv"
if !ERRORLEVEL! equ 0 (
powershell -nop -c "&{[IO.File]::WriteAllText($args[1], [IO.File]::ReadAllText($args[0], [Text.Encoding]::GetEncoding(932)), [TEXT.Encoding]::UTF8)}" \"%%~ff\" \"%%~ff.bom+utf8%%~xf\"
)
)

このスクリプトですとオリジナルのファイルの他にファイル名が「ファイル名.txt.bom+utf8.txt」となり、ファイル数が倍になります。オリジナルの文字コードが変わって上書き保存されるだけで良いです。

私自身は全く技能がありません。すみませんがこのような要望を満たすようスクリプトを変更し、掲示してください。よろしくお願い致します。

投稿日時 - 2018-09-21 19:25:45

QNo.9539566

困ってます

質問者が選んだベストアンサー

今、いろいろサンプルファイルを作成して試してみたのですが、「Null」(中身が空っぽ)のファイルがあるのではないかと思います。

ただ、絶対にそれだけ、とまでは言い切れないので、「Sub x ~ End Sub」の部分を、以下に入れ替えてください。

Sub x
On Error Resume Next
Set ab = CreateObject("ADODB.Stream")
ab.Type = 1
ab.Open
ab.LoadFromFile f & "\" & n.Name
r = ab.Read
ab.Close
a = Hex(Ascb(Midb(r, 1, 1)))
b = Hex(Ascb(Midb(r, 2, 1)))
c = Hex(Ascb(Midb(r, 3, 1)))
d = Hex(Ascb(Midb(r, 4, 1)))
en = "Shift-JIS"
If a = "EF" AND b = "BB" AND c = "BF" Then
en = "UTF-8"
End If
Set ab = Nothing
On Error Goto 0
End Sub

これは、「On Error Resume Next」というエラーが出ても、無視してそのまま処理を続けるようにしたものです。

最後に「On Error Goto 0」で、元に戻しています。

今試したのですが、これで、問題なく処理できました。

なお、もともと空っぽのファイルは変換できないみたいですし、変換に意味もないでしょうから、そのまま残りますが、それはあきらめてください。

投稿日時 - 2018-09-24 18:09:06

お礼

おかげさまでうまく行ったと思います。70GBのフォルダで実行し20分かかりました。テキストファイルは何個あったのかわかりません。


どうもありがとうございました。

投稿日時 - 2018-09-24 19:10:09

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

使い方は同じです。

プログラムファイルの存在するフォルダも処理対象で、プログラムファイルの存在するフォルダを含め、その下のサブフォルダすべてが処理対象になります。

「UTF-8」かどうか判別する「Sub x」を追加しました。

もちろん、「UTF-8」のファイルは処理対象外です。

Option Explicit
Public a, ab, ad, b, c, d, e, en, f, gf, n, r, so
Set so = CreateObject("Scripting.FileSystemObject")
Set f = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
Call y
Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
Call z
Set gf = Nothing
Set so = Nothing
MsgBox("Finished!")

Sub x
Set ab = CreateObject("ADODB.Stream")
ab.Type = 1
ab.Open
ab.LoadFromFile f & "\" & n.Name
r = ab.Read
ab.Close
a = Hex(Ascb(Midb(r, 1, 1)))
b = Hex(Ascb(Midb(r, 2, 1)))
c = Hex(Ascb(Midb(r, 3, 1)))
d = Hex(Ascb(Midb(r, 4, 1)))
en = "Shift-JIS"
If a = "EF" AND b = "BB" AND c = "BF" Then
en = "UTF-8"
End If
Set ab = Nothing
End Sub

Sub y
For Each n In f.Files
e = LCase(so.GetExtensionName(n.Name))
If e = "csv" or e = "txt" Then
Call x
If en = "Shift-JIS" Then
Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "Shift_JIS"
ad.Open
ad.LoadFromFile f & "\" & n.Name
r = ad.ReadText(-1)
ad.Close
Set ad = Nothing
Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "UTF-8"
ad.Open
ad.WriteText r, 0
ad.SaveToFile f & "\" & n.Name, 2
ad.Close
Set ad = Nothing
End If
End If
Next
End Sub

Sub z
For Each f In gf.SubFolders
If f.Attributes <> 22 Then
Call y
End If
Set gf = Nothing
Set gf = so.GetFolder(f)
If gf.Attributes <> 22 Then
Call z
End If
Next
End Sub

説明が必要でしたら、言ってください。

投稿日時 - 2018-09-24 10:07:46

お礼

小規模なフォルダに文字コードが混在したテキストファイルを入れ試したらうまく行ったので本来のフォルダで実行したところ下記エラーが出ました。

行:21
文字:1
エラー:プロシージャの呼び出し、または引数が不正です。:'Ascb'
コード:800A0005
ソース:Microsoft VBscript 実行時エラー

どうしたら良いでしょうか?

いつもありがとうございます。

投稿日時 - 2018-09-24 15:07:32

ANo.2

どのフォルダにも入れずに、ルートフォルダからの実行の場合、実は、ちょっとやっかいなのですが、こちらでは、できています。

「やっかい」というのは、ルートフォルダ内には、見えないシステムフォルダなどがあり、エラーが出るのですが、やっと、回避方法が分かりました。

★★★
なお、注意事項としては、見つかったテキストファイル(「~.csv」・「~.txt」)が、「Shift-JIS」かどうか、という判別をしていません。

見つかったテキストファイルは、必ず、「Shift-JIS」でなければなりません。

すでに「UTF-8」に変換済みのファイルは、文字化けを起こしますので、必ず、変換済みのテキストファイルはどこか別のドライブに待避しておいてください。
★★★

たとえば「D」ドライブなら「D」ドライブのルートフォルダにプログラムファイルを置いてください。

「ダブルクリックで実行」は、同じです。

Option Explicit
Public a, ad, e, f, gf, n, so
Set so = CreateObject("Scripting.FileSystemObject")
Set f = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
Call y
Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
Call z
Set gf = Nothing
Set so = Nothing
MsgBox("Finished!")

Sub y
For Each n In f.Files
e = LCase(so.GetExtensionName(n.Name))
If e = "csv" or e = "txt" Then
Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "Shift_JIS"
ad.Open
ad.LoadFromFile f & "\" & n.Name
a = ad.ReadText(-1)
ad.Close
Set ad = Nothing
Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "UTF-8"
ad.Open
ad.WriteText a, 0
ad.SaveToFile f & "\" & n.Name, 2
ad.Close
Set ad = Nothing
End If
Next
End Sub

Sub z
For Each f In gf.SubFolders
If f.Attributes <> 22 Then
Call y
End If
Set gf = Nothing
Set gf = so.GetFolder(f)
If gf.Attributes <> 22 Then
Call z
End If
Next
End Sub

もし、説明が必要でしたら、言ってください。

投稿日時 - 2018-09-23 18:50:48

お礼

度々のご回答大変有り難うございます。

私の説明が間違っていたらすみません。正確に言うとこのフォルダはNASに作った共有フォルダなのです。これらをネットワークドライブとして運用しています。共有フォルダは数個あり、それぞれの中に数百のフォルダが入っています。私はその共有フォルダをルートディレクトリと表現しました。隠しシステムファイルなどがあったとしても私には関係ないので変換する必要はありません。

また問題点としてテキストファイルの文字コーデはUTF-8とシフトJISが混在しています。おそらく圧倒的多数はシフトJISとおもいます。しかしUTF-8のファイルが文字化けしてしまうと困ります。

以上のような状況に対応できるスクリプトが理想です。


よろしくお願いします。

投稿日時 - 2018-09-23 21:33:53

ANo.1

「bat」は分からないので、「VBScript」による回答です。

以下のプログラムを、メモ帳かテキストエディタに貼り付け、「~.vbs」という名前で保存します。

「~」の部分は、何でもかまいませんが、「.vbs」の部分は、必ず、半角です。

できたプログラムファイル(「~.vbs」ファイル)を、これから処理したい「~.csv」、「~.txt」ファイル群が存在するフォルダに放り込んで、ダブルクリック(「シングルクリック」→「Enter」の方が確実)するだけです。

最後に「Finished!」と表示しますので、「OK」を押して、終了してください。

こちらで、動作確認はしていますが、ある意味、元ファイルがなくなるわけですから、必ず、一度、テスト用のフォルダを作成し、テスト用のファイルで試してから、本番にお使いください。

Option Explicit
Dim a, ad, e, f, gf, so
Set so = CreateObject("Scripting.FileSystemObject")
Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))
For Each f In gf.Files
e = LCase(so.GetExtensionName(f.Name))
If e = "csv" or e = "txt" Then
Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "Shift_JIS"
ad.Open
ad.LoadFromFile gf & "\" & f.Name
a = ad.ReadText(-1)
ad.Close
Set ad = Nothing
Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "UTF-8"
ad.Open
ad.WriteText a, 0
ad.SaveToFile gf & "\" & f.Name, 2
ad.Close
Set ad = Nothing
End If
Next
Set gf = Nothing
Set so = Nothing
MsgBox("Finished!")

簡単な説明です。

Option Explicit

「厳密に」というような意味ですが、気にしないでください。

Set so = CreateObject("Scripting.FileSystemObject")

ファイルやフォルダを扱えるようにしています。

Set gf = so.GetFolder(so.GetParentFolderName(WScript.ScriptFullName))

プログラムファイル(「~.vbs」ファイル)が存在するフォルダ、すなわち、「~.csv」・「~.txt」ファイル群が存在するフォルダを取得しています。

For Each f In gf.Files

プログラムファイルの存在するフォルダ内のすべてのファイルを1つずつ処理。

e = LCase(so.GetExtensionName(f.Name))

見つけたファイルの拡張子を調べています。

If e = "csv" or e = "txt" Then

もし、拡張子が「csv」または「txt」なら、

Set ad = CreateObject("ADODB.Stream")

「UTF-8」を扱うために必要です(最初は「Shift-JIS」ですが)。

ad.Type = 2
ad.Charset = "Shift_JIS"
ad.Open
ad.LoadFromFile gf & "\" & f.Name

見つけたファイルを「読み込み専用」で「Shift-JIS」で開いています。

a = ad.ReadText(-1)

一気に全部読み込んでいます。

ad.Close
Set ad = Nothing

閉じています。

Set ad = CreateObject("ADODB.Stream")
ad.Type = 2
ad.Charset = "UTF-8"
ad.Open

今度は、同じことを「UTF-8」で行います。

ad.WriteText a, 0

先ほど読み込んだ文字列を書き込んでいます。

ad.SaveToFile gf & "\" & f.Name, 2

同じファイル名で、上書き保存しています。

ad.Close
Set ad = Nothing

閉じています。

End If
Next

を、すべてのファイルで繰り返しています。

Set gf = Nothing
Set so = Nothing
MsgBox("Finished!")

あとは、終了処理で、最後に「Finished!」と表示しています。

投稿日時 - 2018-09-23 13:44:44

お礼

丁寧な説明ありがとうございます。

試したところVBSファイルが入っているフォルダではうまく動作しました。しかしその配下のフォルダ内のテキストファイルは変更されません。

理想的にはルートディレクトリに入れて実行すれば配下のフォルダ内全てのファイルが変更されることです。

もしできるのでしたら助かります。どうぞよろしくおねがいします。

投稿日時 - 2018-09-23 17:37:52

あなたにオススメの質問