人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

WSH (Windows Script Host)を使い、言語はVBScriptで、特定のフォルダにあるファイルを別の特定のフォルダに移動させるプログラム(VBSファイル)を作り、そのプログラムをタスクスケジューラで、数分に一度チェックする形で動かすことにしました。

ところが、エラーのため移動できないファイルが出てきました。
そのファイルを調べてみると、MS-DOSファイル名が空であることが分かりました。
VBSでファイル名をチェックしたときに空であるために移動できないようです。
このファイルも移動できるようにするいい方法はないでしょうか?(VBScriptではなく別言語にする、あるいは、VBScriptでもこのようにすればうまく移動できる、など)

ちなみにファイルはMacintosh上で扱っているファイルです。ネットワークでMacintoshのマシンにあるファイルを、Windowsのマシンに移動します。エクスプローラではドラッグ&ドロップで問題なく移動できるので、何か手段はあると思うのですが…。
よろしくお願いします。


●質問者: 敷守ほむら
●カテゴリ:コンピュータ
✍キーワード:Macintosh MS-DOS SCRIPT VBS VBScript
○ 状態 :終了
└ 回答数 : 9/9件

▽最新の回答へ

1 ● venzou
●16ポイント

現在どのような方法で移動させていますか?具体的なソースを教えて下さい。

特にエラーが出ている部分のソース分からないと、回答が難しいと思いますよ。


FileSystemObjectを使っているとすれば、FileオブジェクトのMoveメソッドでエラーが出ると言う事ですか?


もし、FileSystemObjectを使っていなければ、使ってみて下さい。

http://officetanaka.net/excel/vba/filesystemobject/index.htm

◎質問者からの返答

FileSystemObjectは使っています。

Move(MoveFile)は使っていません。CopyFileしてからDeleteFileをしています。(MoveFileだと、移動先にファイルがあった時に上書きできないため。上書きはしてもよいという条件です。)CopyFile(またはCopyFolder)が失敗します。

ちょっと長くなりますがソースを。(フォルダ名などは実際のものと変えてあります。あと、見やすいようにタブを全角スペース2つに置き換えてあります。)

Option Explicit


Const cFolderFrom = "\\ServerFrom\FolderTestFrom" ' 移動元のフォルダ

Const cFolderTo = "\\ServerTo\FolderTestTo" ' 移動先のフォルダ


Dim objWshShell

Dim objFS

Dim objLogFile

On Error Resume Next


'WshShellオブジェクトを生成する

Set objWshShell = WScript.CreateObject("WScript.Shell")


'FileSystemObjectを生成する

Set objFS = WScript.CreateObject("Scripting.FileSystemObject")


'引数があるかチェック

If not (objFS.FolderExists(cFolderFrom)) Then

objWshShell.LogEvent 1, WScript.ScriptFullName & Chr(13) & Chr(10) & "送信元フォルダが未指定。"

Call ExitFunction

ElseIf not (objFS.FolderExists(cFolderTo)) Then

objWshShell.LogEvent 1, WScript.ScriptFullName & Chr(13) & Chr(10) & "送信先フォルダが未指定。"

Call ExitFunction

Else

' MoveFileおよびMoveFolderでは上書きできないためCopyFileおよびCopyFolderを使っています

Set objLogFile = objFS.OpenTextFile(objFS.BuildPath(cFolderTo, "MoveFile.log"), 8, True)

Call WriteFilePathAll (objFS.GetFolder(cFolderFrom), objLogFile)

Dim cntFile, cntFolder

cntFile = 0

cntFolder = 0

If objFS.FileExists(objFS.BuildPath(cFolderFrom, "MoveFile.log")) then

objFS.DeleteFile objFS.BuildPath(cFolderFrom, "MoveFile.log"), False

End If

Call CheckFileAndFolder (objFS.GetFolder(cFolderFrom), cntFile, cntFolder)

If cntFile > 0 then

objFS.CopyFile objFS.BuildPath(cFolderFrom, "*.*"),objFS.BuildPath(cFolderTo, "\"), True

If Err.number = 0 then

objFS.DeleteFile objFS.BuildPath(cFolderFrom, "*.*"), False

If Err.number <> 0 then

objLogFile.WriteLine Now & vbTab & "エラー【1】(" & Err.description & ")"

End If

Else

objLogFile.WriteLine Now & vbTab & "エラー【2】(" & Err.description & ")"

End If

End If

If cntFolder > 0 and Err.number = 0 then

objFS.CopyFolder objFS.BuildPath(cFolderFrom, "*"),objFS.BuildPath(cFolderTo, "\"), True

If Err.number = 0 then

objFS.DeleteFolder objFS.BuildPath(cFolderFrom, "*"), False

If Err.number <> 0 then

objLogFile.WriteLine Now & vbTab & "エラー【3】(" & Err.description & ")"

End If

Else

objLogFile.WriteLine Now & vbTab & "エラー【4】(" & Err.description & ")"

End If

End If

objLogFile.Close

End If


'フォルダ内に含まれるファイルやフォルダを検索する(この関数はWeb上で見つけたものを改造したもの)

Sub WriteFilePathAll(ByVal objFolder, ByVal strm)

' ファイルの書き出し

Dim objFile, files

Set files = objFolder.Files

For Each objFile In files

strm.WriteLine Now & vbTab & objFile.Path

Next

' サブフォルダに対して再帰処理

Dim subfolders, objSub

Set subfolders = objFolder.SubFolders

For Each objSub In subfolders

strm.WriteLine Now & vbTab & objSub.Path

Call WriteFilePathAll( objSub, strm )

Next

End Sub


Sub CheckFileAndFolder(ByVal objFolder, ByRef cntFile, ByRef cntFolder)

' ファイル

Dim objFile, files

Set files = objFolder.Files

For Each objFile In files

cntFile = cntFile + 1

Next

' サブフォルダ

Dim subfolders, objSub

Set subfolders = objFolder.SubFolders

For Each objSub In subfolders

cntFolder = cntFolder + 1

Next

End Sub

問題となっているファイルのみを移動元に置いた状態でプログラムを動かすと、エラー収集用のログには次のようなエラーが出力されます。この時、問題になっているファイルは、移動元には残っており、移動先にはありません。

移動先のフォルダの直下に問題のファイルがある場合には次のエラーです。

エラー【2】(ファイルの名前または数が不正です。)

移動先のフォルダにサブフォルダがあり、その下に問題のファイルがある場合には次のエラーです。

エラー【4】(ファイルの名前または数が不正です。)


問題になっているファイルの名前は「Icon・」(拡張子なし)です。「・」はたぶん文字が表示できなくて「・」になっているものと思われます。プロパティで開いたときに本来ファイル名を表示するテキストボックスが空になっています。サイズは0バイトです。


以上、よろしくお願いします。


2 ● venzou
●16ポイント

問題になっているファイルの名前は「Icon・」(拡張子なし)です。


確認ですが、このファイルはエクスプローラでドラッグ&ドロップで移動出来る状態ですよね?


FileSystemObjectのエラーの原因がよく分からないので、対処するのは難しそうですね。


方法を変えて、コマンドプロンプトからはコピーできますか?


例えば下記のような感じで、コピーした場合どうなります?

Dim objWS
Set objWS = WScript.CreateObject("WScript.Shell")
objWS.Run "cmd.exe /C ""copy """ & cFolderFrom & """ """ & cFolderTo & """ /y /z"""
◎質問者からの返答

はい、該当ファイルはエクスプローラでドラッグ&ドロップで移動出来る状態です。エクスプローラ上でのカット・コピー・ペーストもできます。


コマンドプロンプトから次のコマンドを実行してみました。(フォルダ名は実際のものと変えてあります。)

copy \\ServerFrom\FolderTestFrom \\ServerTo\FolderTestTo /Y /Z

結果は次のようになりました。

\\ServerFrom\FolderTestFrom\Icon
ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。
    0 個のファイルをコピーしました。

3 ● venzou
●16ポイント

COPYがダメなら、XCOPYやMOVEもダメでしょうね


残る方法は、WindowsAPIかな?


VBScriptからは使えないので、VB(VBA)やVCなどでプログラミングが必要です。

面倒くさい上に、これでコピーできる保障もありませが・・・

http://www.winapi-database.com/File/File/index.html


あと思いつく対策は、コピーできそうなフリーウェアを探してみるとか。

http://www.vector.co.jp/vpack/filearea/win/util/file/copy/


あまりお役に立てませんでしたね。ごめんなさい。

◎質問者からの返答

フリーウェアのうち、移動の機能があって人気の高い次の5つのソフトを使って、該当ファイルの移動を指示してみました。

うーん、フリーウェアを使ってもダメそうです。。。


VBやVCでのプログラミングが必要かな、とも思ったのですが、上で試したフリープログラムは全てexeファイルですから、おそらく、exeに変換する前はVBやVC++などで書かれていることが多いと思われるので、やっても無駄な気がします。(ただ、他の言語からもexeは作れますので、その言語で移動ができるというなら可能性はありますが。)


エクスプローラでのドラッグ&ドロップの移動が可能なので、それがどのように動いているか判れば手がかりがつかめるような気もします。


4 ● venzou
●16ポイント

エクスプローラでのドラッグ&ドロップの移動が可能なので、それがどのように動いているか判れば手がかりがつかめるような気もします。

そうですね。逆に、エクスプローラだけ操作可能なのが謎ですね。(^^;


VBやVCでプログラムを書く場合、APIを直接操作せず、言語に用意された標準の関数を使うのが普通です。APIを直接操作して、コピー可能か調べてみる価値はあるかも。


VBA用のAPIを使ったコピーのプログラムを書いてみました。(Excel2000で動作確認)


cFolderFrom フォルダのファイルを cFolderTo へコピーします。サブフォルダはコピーしません。


これで、エラーが出るか出ないか確認してみて下さい。


Option Explicit

Const INVALID_HANDLE_VALUE = &HFFFFFFFF 'エラーのとき
Const MAX_PATH = 256

Type FILETIME
 dwLowDateTime As Long '下位32ビット値
 dwHighDateTime As Long '上位32ビット値
End Type

Type WIN32_FIND_DATA
 dwFileAttributes As Long 'ファイル属性(CreateFile関数を参照)
 ftCreationTime As FILETIME 'ファイルの作成日時
 ftLastAccessTime As FILETIME 'ファイルに最後にアクセスした日時
 ftLastWriteTime As FILETIME 'ファイルに書き込んだ日時
 nFileSizeHigh As Long 'ファイルサイズの上位32ビット値
 nFIleSizeLow As Long '同、下位32ビット値
 dwReserved0 As Long '常に0
 dwReserved1 As Long '常に0
 cFileName As String * MAX_PATH 'ファイル名・ディレクトリ名
 cAlternate As String * 14 'ファイル名
End Type

'dwFileAttributesの定数
Public Const FILE_ATTRIBUTE_ARCHIVE = &H20 'アーカイブ属性
Public Const FILE_ATTRIBUTE_COMPRESSED = &H800 '圧縮ファイル
Public Const FILE_ATTRIBUTE_DIRECTORY = &H10 'ディレクトリ属性
Public Const FILE_ATTRIBUTE_HIDDEN = &H2 '隠しファイル属性
Public Const FILE_ATTRIBUTE_NORMAL = &H80 'ファイル属性をもたない
Public Const FILE_ATTRIBUTE_READONLY = &H1 '読み込み専用属性
Public Const FILE_ATTRIBUTE_SYSTEM = &H4 'システムファイル属性
Public Const FILE_ATTRIBUTE_TEMPORARY = &H100 '一時ファイル属性


Declare Function CopyFile Lib "kernel32.dll" Alias "CopyFileA" _
 (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, _
 ByVal bFailIfExsts As Long) As Long

Declare Function FindFirstFile Lib "kernel32.dll" Alias "FindFirstFileA" _
 (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long

Declare Function FindNextFile Lib "kernel32.dll" Alias "FindNextFileA" _
 (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long

Declare Function FindClose Lib "kernel32.dll" _
 (ByVal hFindFile As Long) As Long

Const cFolderFrom = "\\ServerFrom\FolderTestFrom" ' 移動元のフォルダ
Const cFolderTo = "\\ServerTo\FolderTestTo" ' 移動先のフォルダ

Public Sub test()

 Dim hFind As Long
 Dim FindData As WIN32_FIND_DATA
 Dim Msg As String
 Dim bResult As Long
 
 Dim FileName As String
 Dim ShortName As String
 
 '最初のファイル検索
 hFind = FindFirstFile(cFolderFrom & "\*.*", FindData)

 '検索失敗か?
 If hFind = INVALID_HANDLE_VALUE Then
 MsgBox "検索失敗"
 Exit Sub '******** エラー終了 ********
 End If

 Do
 'ディレクトリは処理しない
 If (FindData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = 0 Then
 
 'NULL文字を取り除く
 FileName = Trim(Left(FindData.cFileName, InStr(FindData.cFileName, vbNullChar) - 1))
 Debug.Print "ファイル名:" & FileName
 
 'コピーする(上書き許可)
 bResult = CopyFile(cFolderFrom & "\" & FindData.cFileName, cFolderTo & "\" & FindData.cFileName, 0)
 If bResult = 0 Then
 MsgBox "コピー失敗:" & FileName
 End If
 End If

 '次を検索
 bResult = FindNextFile(hFind, FindData)

 Loop While bResult <> 0

 '検索の終了
 FindClose hFind

End Sub


後、気になるのは、例のエラーが出るファイルは、MAC側から見るとどうなってます?

◎質問者からの返答

ありがとうございます。


動作させるマシンなんですが、Officeが入っていませんでした。わざわざソースをつけていただいたのに、申し訳ありません。


あと、動作させるマシン、移動元側のマシン、移動先側のマシンについて、次のことがわかりました。

以上の二点に関して、最初お伝えしていたのと条件が変わってしまいました。申し訳ありません。


例のエラーが出るファイルは、MAC側から渡されてきているので、MACでは問題なく扱えています。NAS上では見ることができませんが、MAC側から渡すことができてWinのエクスプローラ上からも見えている状態です。


5 ● venzou
●16ポイント

先ほどのVBAのプログラムですが、ファイル名にUnicodeが含まれているだけで、エラーになりました。これでチェックしても意味無さそうです。失礼しました。



移動元から移動先、および、移動元から動作させるマシンへのカット&ペースト、ドラッグ&ドロップはできませんでした。


こういう事なら、ファイル名にWindowsで使用できない文字が含まれているだけかも知れませんね。

Windows側からは操作できないと思うので、MAC側で対処するしかないのでは?


とりあえず見つけた、MAC用のファイル名をチェックするソフト

非互換ネームcheck

http://www.vector.co.jp/soft/mac/util/se300547.html


探せばもっと便利なソフトがあるかも。

◎質問者からの返答

ちょっとごたごたしてしまいすみません。

移動が目的のため、ファイル名のチェックだけではダメです。

問題のあるファイルの名前を変更してから移動したらうまくできるのでは、とか考えているのですが、今までの状況から言うとWinマシンからファイル名をコマンドプロンプトでチェックできないために変更ができるかどうか疑問です。

あ、あと、回答可能回数を増やしました。


1-5件表示/9件
4.前の5件|次5件6.
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ