そのようなファイルで何かをしようとする前に、それを知る必要があります。
10 に答える
ロックされたディレクトリについては不明 (Windows にはありますか?)
しかし、ファイルが別のプロセスによって書き込まれているかどうかを検出することは難しくありません。
@echo off
2>nul (
>>test.txt echo off
) && (echo file is not locked) || (echo file is locked)
別のウィンドウから次のテスト スクリプトを使用して、ファイルをロックします。
(
>&2 pause
) >> test.txt
1 つのウィンドウから 2 番目のスクリプトを実行し、2 番目のウィンドウから 1 番目のスクリプトを実行すると、「ロックされました」というメッセージが表示されます。最初のウィンドウを押す<Enter>
と、最初のスクリプトを再実行すると、「ロック解除」メッセージが表示されます。
説明
コマンドの出力がファイルにリダイレクトされるときはいつでも、もちろんファイルは書き込みアクセス用に開かれている必要があります。コマンドが出力を生成しない場合でも、Windows CMD セッションはファイルを開こうとします。
リダイレクト演算子は>>
、ファイルを追加モードで開きます。
その>>test.txt echo off
ため、ファイルを開こうとしますが、ファイルに何も書き込まず (echo が既にオフになっていると仮定)、ファイルを閉じます。ファイルは一切変更されません。
ほとんどのプロセスは、書き込みアクセスのためにファイルを開くたびにファイルをロックします。(共有モードで書き込み用にファイルを開くことを許可する OS システムコールがありますが、これはデフォルトではありません)。そのため、別のプロセスがすでに "test.txt" を書き込み用にロックしている場合、リダイレクトは失敗し、次のエラー メッセージが stderr に送信されます - "The process cannot access the file because it is being used by another process." . また、リダイレクトの失敗時にエラー コードが生成されます。コマンドとリダイレクトが成功すると、成功コードが返されます。
コマンドに追加2>nul
するだけでは、リダイレクトではなくコマンドのエラー出力がリダイレクトされるため、エラー メッセージは回避されません。そのため、コマンドを括弧で囲み、エラー出力を括弧の外側で nul にリダイレクトします。
そのため、エラー メッセージは効果的に隠されていますが、エラー コードは依然として括弧の外に伝播されています。標準の Windows&&
と||
演算子は、括弧内のコマンドが成功したか失敗したかを検出するために使用されます。おそらくecho off
失敗することはないので、失敗の唯一の理由はリダイレクトの失敗です。ロックの問題が原因で失敗する可能性が最も高いですが、技術的には他の理由で失敗する可能性があります。
||
演算子が使用されない限り、リダイレクトの失敗時に Windows が %ERRORLEVEL% 動的変数をエラーに設定しないのは興味深い "機能" です。( Windows でのファイルのリダイレクトと %errorlevel% を参照してください)。そのため、||
オペレータは、%ERRORLEVEL% 変数ではなく、返されたエラー コードを低レベルで読み取る必要があります。
これらの手法を使用してリダイレクトの失敗を検出すると、バッチ コンテキストで非常に役立ちます。並列プロセスで複数のイベントをシリアル化できるロックを確立するために使用できます。たとえば、複数のプロセスが「同時に」同じログ ファイルに安全に書き込むことができます。Windows でログ ファイルを共有するにはどうすればよいですか?
編集
ロックされたフォルダについて。おそらくロックを使用して、Windowsがこれをどのように実装しているかはわかりません。ただし、プロセスにフォルダーを含むアクティブなディレクトリがある場合、フォルダーの名前を変更することはできません。これは、を使用して簡単に検出できます
2>nul ren folderName folderName && echo Folder is NOT locked || echo folder is LOCKED
編集
それ以来、(call )
(スペースを含む)は副作用のない非常に高速なコマンドであり、ERRORLEVEL を 0 に設定すると成功することが保証されていることを知りました。また、(スペースを含ま(call)
ない)は副作用のない高速なコマンドであり、ERRORLEVEL 1 で失敗することが保証されています。 .
そのため、次を使用してファイルがロックされているかどうかを確認します。
2>nul (
>>test.txt (call )
) && (echo file is not locked) || (echo file is locked)
dbenhamからの優れた回答に加えて、次のフォームは、使用されているテクニックを理解するのに役立ちます。
( type nul >> file.txt ) 2>nul || echo File is locked!
type nul
コマンドは空の出力を提供し、元のコマンドのように現在のエコー設定には影響しませんecho off
。
if–then–else
正しい順序で条件記憶を使用する場合- 成功ステートメント ( &&
) が最初に実行され、代替ステートメント ( ||
) が 2 番目に実行されます。
command && (echo Command is successful) || (echo Command has failed)
Windows Server 2003リソースキットツールをダウンロードしてインストールするとoh.exe
、特定のファイルの開いているファイルハンドルを一覧表示するというユーティリティがあります。
http://www.microsoft.com/en-us/download/details.aspx?id=17657
インストールしたら、マシンを再起動すると、ユーティリティを使用できるようになります。ヘルプとサポートセンターにすべてのオプションが表示されるほかoh /?
、コマンドプロンプトに入力することもできます。
(情報:http ://windowsxp.mvps.org/processlock.htm )
ファイルの状態を示すメッセージの書き込みは、リターン コードを設定するバッチ コマンドよりも役に立たないことに注意してください。たとえば、ファイルがロックされている場合はコード 1 を返します。
@echo off
2>nul (
>>test.tmp echo off
) && (EXIT /B 0) || (EXIT /B 1)
ちなみに、dbenham のソリューションも、プロセスが実行されているかどうかを調べる効果的な方法のようです。これは、次のアプリケーションで見つけた最良のソリューションでした。
start /b "job1.exe >> job1.out"
start /b /wait "job2.exe >> job2.out"
::wait for job1 to finish using dbenham's code to check if job1.out is in use
comparejobs.exe
:: Create the file Running.tmp
ECHO %DATE% > Running.tmp
ECHO %TIME% >> Running.tmp
:: block it and do the work
(
>&2 CALL :Work 30
) >> Running.tmp
:: when the work is finished, delete the file
DEL Running.tmp
GOTO EOF
:: put here the work to be done by the batch file
:Work
ping 127.0.0.1 -n 2 -w 1000 > NUL
ping 127.0.0.1 -n %1 -w 1000 > NUL
:: when the process finishes, the execution go back
:: to the line after the CALL