Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check in command-line if a given file or directory is locked (used by any process)?

I need to know that before any attempt to do anything with such file.

like image 887
rsk82 Avatar asked May 09 '12 14:05

rsk82


People also ask

What is the command that is used to find out which folder you are in?

You can always find the directory you are in using the pwd command.


2 Answers

Not sure about locked directories (does Windows have that?)

But detecting if a file is being written to by another process is not difficult.

@echo off
2>nul (
  >>test.txt echo off
) && (echo file is not locked) || (echo file is locked)

I use the following test script from another window to place a lock on the file.

(
  >&2 pause
) >> test.txt

When I run the 2nd script from one window and then run the 1st script from a second window, I get my "locked" message. Once I press <Enter> in the 1st window, I get the "unlocked" message if I rerun the 1st script.

Explanation

Whenever the output of a command is redirected to a file, the file of course must be opened for write access. The Windows CMD session will attempt to open the file, even if the command does not produce any output.

The >> redirection operator opens the file in append mode.

So >>test.txt echo off will attempt to open the file, it writes nothing to the file (assuming echo is already off), and then it closes the file. The file is not modified in any way.

Most processes lock a file whenever they open a file for write access. (There are OS system calls that allow opening a file for writing in a shared mode, but that is not the default). So if another process already has "test.txt" locked for writing, then the redirection will fail with the following error message sent to stderr - "The process cannot access the file because it is being used by another process.". Also an error code will be generated upon redirection failure. If the command and the redirection succeed, then a success code is returned.

Simply adding 2>nul to the command will not prevent the error message because it redirects the error output for the command, not the redirection. That is why I enclose the command in parentheses and then redirect the error output to nul outside of the parens.

So the error message is effectively hidden, but the error code is still propagated outside of the parens. The standard Windows && and || operators are used to detect whether the command inside the parens was successful or failed. Presumably echo off will never fail, so the only possible reason for failure would be the redirection failed. Most likely it fails because of a locking issue, though technically there could be other reasons for failure.

It is a curious "feature" that Windows does not set the %ERRORLEVEL% dynamic variable to an error upon redirection failure unless the || operator is used. (See File redirection in Windows and %errorlevel%). So the || operator must read the returned error code at some low level, not via the %ERRORLEVEL% variable.

Using these techniques to detect redirection failure can be very useful in a batch context. It can be used to establish locks that allow serialization of multiple events in parallel processes. For example, it can enable multiple processes to safely write to the same log file at the "same" time. How do you have shared log files under Windows?


EDIT

Regarding locked folders. I'm not sure how Windows implements this, perhaps with a lock. But if a process has an active directory involving the folder, then the folder cannot be renamed. That can easily be detected using

2>nul ren folderName folderName && echo Folder is NOT locked || echo folder is LOCKED

EDIT

I have since learned that (call ) (with a space) is a very fast command without side effects that is guaranteed to succeed with ERRORLEVEL set to 0. And (call) (without a space) is a fast command without side effects that is guaranteed to fail with ERRORLEVEL 1.

So I now use the following to check if a file is locked:

2>nul (
  >>test.txt (call )
) && (echo file is not locked) || (echo file is locked)
like image 52
dbenham Avatar answered Oct 23 '22 11:10

dbenham


In addition to great answer from dbenham, the following form finally help me understand used technique:

( type nul >> file.txt ) 2>nul || echo File is locked!

type nul command gives an empty output and does not affect the current echo setting like echo off command in orginal.

If you want to use if–then–else condition remember of correct order - success statement (&&) is going first and alternate statement (||) is going second:

command && (echo Command is successful) || (echo Command has failed) 
like image 28
lukk Avatar answered Oct 23 '22 11:10

lukk