Как проверить в командной строке, заблокирован ли данный файл или каталог (используется любым процессом)?
Мне нужно знать, что перед любой попыткой сделать что-либо с таким файлом.
7 ответов
не уверен в заблокированных каталогах (есть ли у Windows это?)
но определить, записывается ли файл другим процессом, не сложно.
@echo off
2>nul (
>>test.txt echo off
) && (echo file is not locked) || (echo file is locked)
я использую следующий тестовый скрипт из другого окна, чтобы заблокировать файл.
(
>&2 pause
) >> test.txt
когда я запускаю 2-й скрипт из одного окна, а затем запускаю 1-й скрипт из второго окна, я получаю свое "заблокированное" сообщение. Как только я нажму <Enter>
в 1-м окне, я получаю сообщение "разблокировано" если я перезапущу 1-й сценарий.
объяснение
всякий раз, когда вывод команды перенаправляется в файл, файл конечно должен быть открыт для записи. Сеанс CMD Windows попытается открыть файл, даже если команда не выдает никаких выходных данных.
на >>
оператор перенаправления открывает файл в режиме добавления.
так >>test.txt echo off
попытается открыть файл, он ничего не записывает в файл (при условии, что echo уже выключен), а затем он закрывает файл. Файл никоим образом не изменяется.
самые процессы блокировки файла при открытии файла для записи. (Есть системные вызовы ОС, которые позволяют открывать файл для записи в общем режиме, но это не по умолчанию). Поэтому, если другой процесс уже имеет "тест".txt " заблокирован для записи, затем перенаправление завершится ошибкой со следующим сообщением об ошибке, отправленным в stderr -"процесс не может получить доступ к файлу потому что он используется другим процессом.". Также при сбое перенаправления будет сгенерирован код ошибки. Если команда и перенаправление выполняются успешно, возвращается код успеха.
просто добавив 2>nul
команде не предотвратит сообщение об ошибке, потому что оно перенаправляет вывод ошибки для команды, а не перенаправление. Вот почему я заключаю команду в круглые скобки, а затем перенаправляю вывод ошибки на nul вне фаренс.
таким образом, сообщение об ошибке эффективно скрыто, но код ошибки по-прежнему распространяется за пределами родителей. Стандартный Windows &&
и ||
операторы используются для определения того, была ли команда внутри parens успешной или неудачной. Предположительно echo off
никогда не потерпит неудачу, поэтому единственной возможной причиной сбоя будет сбой перенаправления. Скорее всего, это происходит из-за проблемы блокировки, хотя технически могут быть и другие причины неудача.
любопытная "особенность", что Windows не устанавливает динамическую переменную %ERRORLEVEL% в ошибку при сбое перенаправления, если оператор. (См.перенаправление файлов в Windows и %errorlevel%). Так что ||
оператор должен считывать возвращаемый код ошибки на некотором низком уровне, а не через переменную %ERRORLEVEL%.
использование этих методов для обнаружения сбоя перенаправления может быть очень полезно в контексте пакета. Его можно использовать установить блокировки, позволяющие сериализацию нескольких событий в параллельных процессах. Например, он может позволить нескольким процессам безопасно записывать в один и тот же файл журнала одновременно. как у вас есть общие файлы журналов под Windows?
редактировать
в отношении заблокированных папок. Я не уверен, как Windows реализует это, возможно, с замком. Но если процесс имеет active directory с участием папки, то папку нельзя переименовать. Это можно легко обнаружить с помощью
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)
кроме отличный ответ!--9--> из dbenham, следующая форма, наконец, поможет мне понять используемую технику:
( type nul >> file.txt ) 2>nul || echo File is locked!
type nul
команда дает пустой вывод и не влияет на текущую настройку Эха, такую как echo off
команда в оригинале.
если вы хотите использовать if–then–else
условие помните о правильном порядке-заявление об успехе (&&
) идет первый и альтернативный оператор (||
) будет второй:
command && (echo Command is successful) || (echo Command has failed)
при загрузке и установке Windows Server 2003 Resource Kit Tools существует утилита под названием oh.exe
Что будет список открытых дескрипторов файлов для данного архива:
http://www.microsoft.com/en-us/download/details.aspx?id=17657
после его установки перезагрузите компьютер, и вы сможете использовать утилиту. Вы можете просмотреть все параметры в центре справки и поддержки, а также введя oh /?
в командной строке.
(информация от : http://windowsxp.mvps.org/processlock.htm )
обратите внимание, написание сообщение статус файла был менее полезны, чем команда batch, которые устанавливают код. Например, код возврата 1, Если файл заблокирован.
@echo off
2>nul (
>>test.tmp echo off
) && (EXIT /B 0) || (EXIT /B 1)
просто я хочу поделиться с вами примером моего скрипта, основанного на трюке @dbenham
описание этого скрипта: Check_Locked_Files.летучая мышь : Этот скрипт может сканировать и проверять заблокированные файлы в наборе папок, которые могут быть изменены в скрипте; например, я выбрал набор папок для сканирования:
Set Folders=^
^ "%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%UserProfile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%ProgramFiles%\Internet Explorer"^
^ "%ProgramFiles%\Skype"^
^ "%ProgramFiles%\TeamViewer"^
^ "%WinDir%\system32\drivers"^
^ "%Temp%"
результат вывода в формате HTML для большей читаемости.
Если файл заблокирован, мы покажем он в красном цвете, иначе мы покажем его в зеленом цвете.
и весь скрипт : Check_Locked_Files.летучая мышь!--7-->
@echo off
Rem This source is inspired from here
Rem hxxps://stackoverflow.com/questions/
Rem 10518151/how-to-check-in-command-line-if-a-given-file-or-directory-is-locked-used-by-any?answertab=active#tab-top
Rem Thanks for dbenham for this nice trick ;)
Mode con cols=90 lines=5 & color 9E
Title Scan and Check for Locked Files by Hackoo 2017
set "LogFile=%~dp0%~n0.html"
(
echo ^<html^>
echo ^<title^> Scan and Check for locked files by Hackoo 2017^</title^>
echo ^<body bgcolor^=#ffdfb7^>
echo ^<center^>^<b^>Log Started on %Date% @ %Time% by the user : "%username%" on the computer : "%ComputerName%"^</b^>^</center^>
)> "%LogFile%"
echo(
echo --------------------------------------------------------------------------
echo Please Wait a while ....... Scanning for locked files is in progress
echo --------------------------------------------------------------------------
Rem We Play radio just for fun and in order to let the user be patient until the scan ended
Call :Play_DJ_Buzz_Radio
Timeout /T 3 /nobreak>nul
cls
Set Folders=^
^ "%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%UserProfile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%ProgramFiles%\Internet Explorer"^
^ "%ProgramFiles%\Skype"^
^ "%ProgramFiles%\TeamViewer"^
^ "%WinDir%\system32\drivers"^
^ "%Temp%"
@For %%a in (%Folders%) Do (
( echo ^<hr^>^<font color^=DarkOrange^>^<B^>Folder : %%a^</B^>^</font^>^<hr^>) >> "%LogFile%"
@for /f "delims=" %%b in ('Dir /A-D /s /b "%%~a\*.*"') do (
Call :Scanning "%%~nxb"
Call:Check_Locked_File "%%~b" "%LogFile%"
)
)
(
echo ^<hr^>
echo ^<center^>^<b^>Log ended on %Date% @ %Time% on the computer : "%ComputerName%"^</b^>^</center^>
echo ^</body^>
echo ^</html^>
)>> "%LogFile%"
Start "" "%LogFile%" & Call :Stop_Radio & exit
::***********************************************************************************
:Check_Locked_File <File> <LogFile>
(
2>nul (
>>%1 (call )
) && ( @echo ^<font color^=green^>file "%~1"^</font^>^<br^>
) || (
@echo ^<font color^=red^>file "%~1" is locked and is in use^</font^>^<br^>
)
)>>%2 2>nul
exit /b
::***********************************************************************************
:Scanning <file>
cls
echo(
echo --------------------------------------------------------------------------
echo Please Wait a while... Scanning for %1
echo --------------------------------------------------------------------------
exit /b
::***********************************************************************************
:Play_DJ_Buzz_Radio
Taskkill /IM "wscript.exe" /F >nul 2>&1
Set "vbsfile=%temp%\DJBuzzRadio.vbs"
Set "URL=http://www.chocradios.ch/djbuzzradio_windows.mp3.asx"
Call:Play "%URL%" "%vbsfile%"
Start "" "%vbsfile%"
Exit /b
::**************************************************************
:Play
(
echo Play "%~1"
echo Sub Play(URL^)
echo Dim Sound
echo Set Sound = CreateObject("WMPlayer.OCX"^)
echo Sound.URL = URL
echo Sound.settings.volume = 100
echo Sound.Controls.play
echo do while Sound.currentmedia.duration = 0
echo wscript.sleep 100
echo loop
echo wscript.sleep (int(Sound.currentmedia.duration^)+1^)*1000
echo End Sub
)>%~2
exit /b
::**************************************************************
:Stop_Radio
Taskkill /IM "wscript.exe" /F >nul 2>&1
If Exist "%vbsfile%" Del "%vbsfile%"
::**************************************************************
кстати, решение 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