【问题标题】:Check if Windows file is redirected to itself检查 Windows 文件是否被重定向到自身
【发布时间】:2015-03-31 05:06:44
【问题描述】:

我试图弄清楚如何测试文件是否被重定向到自身,例如.\command.exe file1 > file1

在 *nix 世界中,我只会使用这样的东西:

// Language agnostic...
if (file_dev == out_dev && file_ino == out_ino) {
    printf("%s\n", "same file!");
}

但在 Windows 中,如果我尝试这样做:

// This (language) is Go...
// create fileStat...

// now stat stdout
outStat, err := os.Stdout.Stat()
// error check

if os.SameFile(fileStat, outStat) {
    fmt.Println("same file!")
}

...我收到 IncorrectFunction 错误。

我阅读了这个 (https://stackoverflow.com/a/21070042/2967113) 问题,据我所知,您无法统计 stdout

这是一个主要与语言无关的问题——我可以将任何内容翻译成 Go(我正在使用的语言)。我最关心的是如何,使用 Windows 的 ABI(API?),我会找到 stdout 被重定向到的位置。

【问题讨论】:

标签: windows stdout


【解决方案1】:

这个答案是特定于 Windows 的,但是当你标记为“windows”时,我认为没关系。

我对 Go 无能为力,但在 C/C++ 中你可以这样做:

#include <tchar.h>
#include <Windows.h>
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t chPath[MAX_PATH];
    if (GetFinalPathNameByHandle(GetStdHandle(STD_OUTPUT_HANDLE), chPath, MAX_PATH, 0))
        std::wcout << L"stdout = " << chPath << std::endl;
    else
        std::cout << "stdout not redirected" << std::endl;

    return 0;
}

如果 stdout 是控制台句柄,GetFinalPathNameByHandle 将失败,但如果它被重定向到文件,它将返回文件路径。

【讨论】:

  • 我想这回答了所提出的具体问题,但由于我的回答中涵盖的原因,我仍然认为它不会有任何好处。当你发现它时,为时已晚。
【解决方案2】:

【讨论】:

  • 成功了!我接受了乔纳森的,因为他是第一位的——希望你能理解。再次感谢。
【解决方案3】:

嗯,首先,我不认为你在 UNIX 领域的方法实际上会保护你。

当您的代码开始检查设备和 inode 时,shell 已经已经截断了文件。 负责处理输出重定向,它会在您的程序启动之前执行此操作,以便为您的输出提供一个新文件。

我怀疑你在 Windows 中也会遇到同样的问题,cmd.exe 会在你的脚本开始运行之前截断你的文件。

话虽如此,我相信在某些时候你将不得不相信用户知道他们在做什么:-)

当然,另一种选择是不输出重定向,而是要求输入和输出文件作为参数:

cmd.exe myscipt myscript

这样,您可以检测用户是否要写入输入文件(使用规范化的文件名或 inode)并阻止它。

虽然仍然不会阻止用户做一些愚蠢的事情:

cmd.exe myscipt >myscript

在您有机会通知他们应该提供两个参数而不是一个参数之前吹掉你的脚本。

我认为底线是,如果用户进行了输出重定向,那么您的 程序 无法在为时已晚之前捕捉到它。

【讨论】:

  • 第一部分(截断)是正确的,我知道这一点。 :-) 这主要是为了我,因为我正在将 GNU 的 coreutils 从 C 音译到 Go,并且我希望它们尽可能地尽可能相似。它还可以防止这样的事情:stackoverflow.com/a/26112133/2967113
  • @eric,我不完全确定你认为你的方案会保护什么,它不会像脚本覆盖本身那样做:script &gt;script因为,如上所述,覆盖发生在脚本开始运行之前很久。也许你可以解释更多。
  • 使用 BSD cat,如果您执行 cat file1 file2 &gt; file2 之类的操作,可能会导致无限循环。真的,这没什么大不了的。但它(检查)是 GNU cat 的一部分,这就是我要复制的 cat,所以我想包含它!
猜你喜欢
  • 2010-11-13
  • 2011-11-24
  • 2012-06-16
  • 2012-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多