检查Windows文件是否重定向到自身

检查Windows文件是否重定向到自身,windows,stdout,Windows,Stdout,我试图找出如何测试文件是否被重定向到自身,例如\command.exe file1>file1 在*nix世界中,我只会使用这样的东西: #include <tchar.h> #include <Windows.h> #include <iostream> int _tmain(int argc, _TCHAR* argv[]) { wchar_t chPath[MAX_PATH]; if (GetFinalPathNameByHandle(

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

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

#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;
}
//语言不可知论者。。。
如果(文件\u dev==out\u dev&&file\u ino==out\u ino){
printf(“%s\n”,“同一文件!”);
}
但在Windows中,如果我尝试这样做:

//这(语言)是Go。。。
//创建文件状态。。。
//现在统计数据
outStat,err:=os.Stdout.Stat()
//错误检查
if os.SameFile(fileStat,outStat){
Println(“同一文件!”)
}
…我得到了
不正确的函数
错误

我读了这个()问题,从我收集的信息来看,你不能统计标准值吗


这是一个语言不可知的问题——我可以翻译任何东西(我正在使用的语言)。我最关心的是如何使用Windows的ABI(API?)找到stdout被重定向到的位置。

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

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

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

话虽如此,我相信在某种程度上,您将不得不相信用户知道他们在做什么:-)

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

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

尽管这仍然不能阻止用户做一些愚蠢的事情,比如:

cmd.exe myscipt >myscript
在你有机会通知他们之前,把你的脚本吹走他们应该提供两个参数而不是一个


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

这个答案是特定于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;
}
#包括
#包括
#包括
int _tmain(int argc,_TCHAR*argv[]
{
wchar_t chPath[最大路径];
if(GetFinalPathNameByHandle(GetStdHandle(STD\u OUTPUT\u HANDLE),chPath,MAX\u PATH,0))
std::wcout您可以调用打开文件句柄

然后打电话

最后,打电话


获取文件路径名并比较名称的等效性。

我拒绝了您的编辑,因为这是关于Windows'A{B,p}的。我不去…对不起。没关系。在重新阅读问题后对我有意义。第一部分(截断)是真的,我知道。:-)这主要是为了我的缘故,因为我把GNU的coreutils从C翻译成Go,我希望它们尽可能的相似。它还可以防止类似的情况:@eric,我不完全确定你认为你的方案会防止什么,它不会这样做,因为像脚本重写本身这样的事情:<代码>脚本>脚本
因为,如上所述,覆盖发生在脚本开始运行之前很久。也许您可以解释更多。使用BSD
cat
如果您执行类似于
cat file1 file2>file2
的操作,可能会导致无限循环。确实,这没什么大不了的。但是(检查)是GNU
cat
的一部分,这就是我正在复制的
cat
,所以我想把它包括在内!我想这回答了所问的具体问题,但我仍然不认为这有什么好处,因为我的答案中包含的原因。当你发现它时,为时已晚。它起作用了!我接受了乔纳森的,因为他先来了——希望你明白了,再次谢谢。