command-line - 如果给定文件或目录被锁定(由任何进程使用),如何检查命令行?

标签 command-line batch-file windows-xp filelock

在尝试对此类文件执行任何操作之前,我需要知道这一点。

最佳答案

不确定锁定的目录(Windows 有吗?)

但是检测一个文件是否正在被另一个进程写入并不困难。

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

我使用另一个窗口中的以下测试脚本来锁定文件。
(
  >&2 pause
) >> test.txt

当我从一个窗口运行第二个脚本,然后从第二个窗口运行第一个脚本时,我收到“锁定”消息。一旦我按 <Enter>在第一个窗口中,如果我重新运行第一个脚本,我会收到“解锁”消息。

解释

每当命令的输出被重定向到文件时,当然必须打开文件以进行写访问。 Windows CMD session 将尝试打开文件,即使该命令没有产生任何输出。
>>重定向运算符以附加模式打开文件。

所以>>test.txt echo off将尝试打开文件,它不向文件写入任何内容(假设 echo 已经关闭),然后关闭文件。该文件不会以任何方式修改。

大多数进程在打开文件进行写访问时都会锁定文件。 (有一些操作系统系统调用允许打开文件以在共享模式下写入,但这不是默认设置)。因此,如果另一个进程已经锁定了“test.txt”以进行写入,那么重定向将失败,并发送以下错误消息到 stderr -“该进程无法访问该文件,因为它正在被另一个进程使用。”。重定向失败时也会生成错误代码。如果命令和重定向成功,则返回成功代码。

只需添加 2>nul到命令不会阻止错误消息,因为它重定向命令的错误输出,而不是重定向。这就是为什么我将命令括在括号中,然后将错误输出重定向到括号外的 nul 。

所以错误消息被有效地隐藏了,但错误代码仍然在括号之外传播。标准 window &&||运算符用于检测括号内的命令是成功还是失败。大概是echo off永远不会失败,因此失败的唯一可能原因是重定向失败。它很可能是由于锁定问题而失败,尽管从技术上讲可能还有其他失败原因。

一个奇怪的“功能”是 Windows 在重定向失败时不会将 %ERRORLEVEL% 动态变量设置为错误,除非 ||使用运算符。 (见 File redirection in Windows and %errorlevel%)。所以||运算符(operator)必须在某个低级别读取返回的错误代码,而不是通过 %ERRORLEVEL% 变量。

使用这些技术来检测重定向失败在批处理上下文中非常有用。它可用于建立允许在并行进程中序列化多个事件的锁。例如,它可以使多个进程在“同一”时间安全地写入同一个日志文件。 How do you have shared log files under 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)

关于command-line - 如果给定文件或目录被锁定(由任何进程使用),如何检查命令行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10518151/

相关文章:

perl - 如何使用 Perl 替换 grep 来保留文件名

windows - 如何将输出重定向到名称为当前日期和时间的文件?

batch-file - 在 if 语句 = 上做 2 件事

git - 适用于 Windows 的 Vim - 我应该输入什么来保存和退出文件?

linux - 我错误地发出了命令

android - 设置 Android AVD 命令行硬件配置文件

vba - 如何从批处理文件中仅打开 Excel 宏的用户窗体

path - 批处理 : getting the last folder name from a absolute path

c - 如何找到线程运行的处理器编号?

c# - 文件流到字节 [] : Windows XP vs Windows 8