在 Windows NTFS 文件系统上,我有一个文件(例如orig.mp3
)。我通过此路径打开此文件orig.mp3
,以便可以使用它(例如,通过在 VLC 中播放它)。
然后我创建一个硬链接(cmd /c mklink /h link.mp3 orig.mp3
)。这会导致两个 NTFS 路径指向完全相同的文件。
最后,我尝试再次删除链接文件(del link.mp3
或在 Windows 资源管理器中删除)。
失败并出现错误:“该进程无法访问该文件,因为该文件正在被另一个进程使用。”
为什么?更重要的是:我该如何避免这种情况(除了确保没有进程正在使用原始文件)?我是否可以告诉 Windows 执行“延迟删除”,以便在原始文件不再使用时自动删除链接文件?
答案1
这是意料之中的行为,硬链接只是同一文件的另一个名称。例如,如果您有文件 A.PDF,请创建指向同一文件的硬链接 B.PDF,无论文件是以名称 A.PDF 还是 B.PDF 打开的,它仍然是同一个文件,因此如果只是打开此文件,则无法删除任一链接。
实际的原因是,该名称作为属性存储在主文件表的文件记录中(对于 NTFS),并且由于该文件已打开,因此您无法删除任一链接(您无法修改已打开的文件)。
在这种情况下,没有像原始文件那样的东西,因为两个名称都属于同一个(也是唯一的)文件,并且两个名称是相等的。当链接计数达到零时,文件实际上会被删除。
答案2
虽然上述关于何时以及为什么可以或不能删除硬链接的答案并不完全错误,但可以通过以下链接找到更精确的原因:
FILE_SHARE_DELETE
CreateFileA
文档中的链接。
如果未指定此标志,但文件或设备已打开以进行删除访问,则该功能失败。
如果该文件的任何句柄(包括其硬链接对等体)未获得打开权限,则请求 dwDesiredAccess 时调用CreateFile
将失败。DELETE
FILE_SHARE_DELETE
这就是尝试删除硬链接可能失败的一般原因(error code 5 access violation
);要求必须关闭该文件的所有打开的硬链接对等体才能删除硬链接。
创建/删除指向可执行文件(可能是 nodejs/npm)的硬链接是一种常见的模式,以便 nix-busybox 风格的 EXE 名称别名共享单个 EXE 二进制文件。
对于硬链接的可执行文件,删除硬链接具有硬链接对等体的可执行文件跑步将会失败,因为 Windows 加载程序没有以FILE_SHARE_DELETE
权限打开可执行文件。这使得通过删除来管理安装、移除/更新的硬链接变得非常烦人,因为在运行服务执行程序时,您使用共享执行程序硬链接对等命名来创建这些服务执行程序。作为一种模式,如果您遇到此问题,请改用符号链接。不过,与硬链接不同,任何进程查看器(或类似的进程枚举 API)中的服务执行程序都将使用符号链接目标名称而不是符号链接名称 [叹气])。
硬链接共享 NTFS 文件描述是正确的。
即卷上的结构相同。另请注意,硬链接共享相同的 NTFS
FILE_ID_INFO
看GetFileInformationByHandleEx - FileIdInfo (0x12)
。
但这并不是您无法在对等链接打开时删除硬链接的原因。事实进一步证明了这一点:即使对等链接打开,您也可以为任何对等硬链接创建更多硬链接;尽管您无法在任何对等链接打开时未经许可删除它们FILE_SHARE_DELETE
。
如何在打开对等链接的情况下删除硬链接
- 使用可以显示硬链接对等体的工具。
- 使用一个工具来显示对硬链接或其对等方开放句柄的进程。手动关闭/终止它们。
- 使用文件监视工具或使用文件监视 API,在所有硬链接对等体关闭时删除硬链接(通过 #2)。
- 使用上面提到的 Win32
MoveFileEx
与MOVEFILE_DELAY_UNTIL_REBOOT
并等待/需要重新启动才能删除硬链接。
作为参考,我有一个使用这些类型的硬链接模式的工具集。它可以执行上述所有操作(它是一个通用的 shell 和动态语言
ess
)。该工具集是边缘壳使用一个名为 的无需安装的二进制文件afm.exe
。
API 注意事项DeleteFile
:要执行与dwFlagsAndAttributes相同的操作,只需要FILE_FLAG_DELETE_ON_CLOSE
和FILE_FLAG_OPEN_REPARSE_POINT
(正确处理符号链接和连接重新解析点而不是它们的目标)。
API 注意事项FindFirstFileNameW
:您可以使用、FindNextFileNameW
和枚举所有硬链接对等点FindClose
。硬链接对等点只是指向 NTFS 文件节点的另一个 NTFS 目录节点条目名称引用(路径名)。由于它们共享 NTFS 卷的文件本身和指向目录节点的硬链接外部引用(反向指针),因此信息保存在该文件节点中,硬链接不得不在同一个 NTFS 卷上。
笔记:复制到硬链接文件和 NTFS 文件共享的重新解析点
这可能非常不直观,如果您使用大多数命令行或编辑器工具将文件复制到硬链接上,它通常会删除/破坏硬链接并创建该文件的新独立副本。
如果您的目标是实际替换硬链接文件的内容,以便硬链接及其所有对等体可以共享复制的数据,那么您通常需要一个可以感知该操作的硬链接的工具(w/wo 标志选项)。
如果您没有这样的工具,最好“打开”有问题的硬链接文件并“写入”所需的新内容(不要使用通用文件复制工具)。请注意,许多 IDE 编辑器(VsCode、Visual Studio)将使用 std c-lib api,这些 api 实际上会删除然后替换文件(破坏您的硬链接)。 这可能会变得非常令人困惑。
Windows 世界一直具有强大的 NTFS 功能,但长期缺乏用于处理硬链接、符号链接(和连接)的 nix 知识和工具。
文件共享和链接:事实上,JUNCTIONS 非常棒。特别是当您了解 NTFS 卷的网络文件共享中 JUNCTIONS 和 SYMLINK 重新解析点的处理方式之间的真正区别时。
即,SYMLINK 在 CLIENT 机器上解析,而 JUNCTION 在 SERVER 机器上解析。
这意味着具有符号链接(例如 C:\something)的 NTFS 卷将查找客户端计算机的 C 驱动器(因为该链接在客户端上解析),但 JUNCTION 将查找服务器的 C 驱动器(因为该链接在服务器上解析)并因此解析服务器上的路径并且不会向客户端公开连接重新解析。
有关配置 NTFS 共享行为,请参阅
symlinkevaluation <symboliclinktype>
控制可在计算机上创建的符号链接类型。有效选项包括:
- 本地到本地符号链接,L2L:{0|1}
- 本地到远程符号链接,L2R:{1|0}
- 远程到本地符号链接,R2L:{1|0}
- 远程到远程符号链接,R2R:{1|0}
答案3
详情Robert Goldwein 的回答,当文件正在使用时,无法删除此类硬链接。不过,延迟删除是可能的。
达蒙对这个问题的评论建议使用移动文件来自 Sysinternals Suite。
就我而言,如果我想通过 PowerShell 执行此操作,我可以使用 Lee Holmes 的Move-LockedFile
link.mp3 $null
,让 Windows 在下次启动时删除该文件。
以上两个函数都使用 Win32 MoveFileEx 函数移动文件延迟直至重启旗帜。
更新:看https://gist.github.com/marnix/7565364我Remove-File-Eventually
刚刚破解了。不保证。:-)
答案4
mklink
是一个CMD内部的命令,在 FAT FS 上不起作用。要删除硬链接,您需要退出所有可能使用它的程序,包括 Powershell 运行的程序。退出所有程序并启动新的命令以管理员身份,然后使用文件系统工具: cmd /c fsutil hardlink list <hardlinked_filename/dir>
,以确保它是什么类型的链接。(请注意,此功能不能直接从 W10 CMD 提示符获得。)您也可以尝试 或cmd /c dir /A:S
。
要删除,请使用德尔和cmd /c del hardlinked_file.exe
(在 CMD shell 中)或进入 WSL 并尝试从那里删除它,因为它(可能)更擅长处理符号链接删除。如果这不起作用,请使用系统内部工具;movefile64.exe
并pendmoves64.exe
检查。
作为最后的手段,你可能想要安装HardLinkShellExt可以创建、调整和删除各种符号链接。但是,这是一个高级工具,如果不具备丰富的技术知识,很难理解。