पता लगाएँ कि क्या स्टडिन एक टर्मिनल या पाइप है?


118

जब मैं pythonटर्मिनल से " " निष्पादित करता हूं तो बिना किसी तर्क के यह पायथन इंटरेक्टिव शेल को लाता है।

जब मैं cat | pythonटर्मिनल से " " निष्पादित करता हूं तो यह इंटरैक्टिव मोड को लॉन्च नहीं करता है। किसी तरह, बिना किसी इनपुट के, यह पता चला है कि यह एक पाइप से जुड़ा है।

मैं C या C ++ या Qt में समान पहचान कैसे करूंगा?


7
आप जो चाहते हैं वह यह पता लगाने के लिए नहीं है कि स्टड एक पाइप है, लेकिन अगर स्टडिन / स्टडआउट एक टर्मिनल है।
जूलियानो

जवाबों:


137

उपयोग करें isatty:

#include <stdio.h>
#include <io.h>
...    
if (isatty(fileno(stdin)))
    printf( "stdin is a terminal\n" );
else
    printf( "stdin is a file or a pipe\n");

(विंडोज़ पर वे अंडरस्कोर के साथ उपसर्ग कर रहे हैं: _isatty, _fileno)


13
+1: स्टडिन एक पाइप हो सकती है या किसी फ़ाइल से पुनर्निर्देशित हो सकती है। अगर यह बेहतर जाँच करने के लिए है इंटरैक्टिव अगर यह होता है की जाँच करने के से नहीं
जॉन कुगेलमैन

51
POSIX पर कोई भी नहीं है io.hऔर इसके लिए isatty()आपको शामिल करने की आवश्यकता है unistd.h
मैक्सचेलपिजिग सेप

अनुवर्ती प्रश्न: स्टड के मामले में पाइप की गई सामग्री को कैसे पढ़ना है? stackoverflow.com/q/16305971/96656
मैथियास ब्यनेंस

नोट: यदि आपको यह देखना है कि क्या आप आउटपुट को दबाते हैं या नहीं, तो यदि आप देखना चाहते हैं कि स्टडआउट (STDOUT_FILENO) को चेक करना है या नहीं less
कोर

71

सारांश

कई उपयोग के मामलों के लिए POSIX फ़ंक्शन isatty()सभी है जो यह पता लगाने के लिए आवश्यक है कि क्या स्टडिन एक टर्मिनल से जुड़ा हुआ है। एक न्यूनतम उदाहरण:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  if (isatty(fileno(stdin)))
    puts("stdin is connected to a terminal");
  else
    puts("stdin is NOT connected to a terminal");
  return 0;
}

निम्नलिखित अनुभाग विभिन्न तरीकों की तुलना करता है जिनका उपयोग किया जा सकता है यदि अन्तरक्रियाशीलता के विभिन्न डिग्री का परीक्षण किया जाना है।

विस्तार से तरीके

यह पता लगाने के लिए कई तरीके हैं कि क्या कोई कार्यक्रम अंतःक्रियात्मक रूप से चल रहा है। निम्नलिखित तालिका एक अवलोकन दिखाती है:

cmd \ पद्धति ctermid खुले इस् ट्टी फ़ासत
-------------------------------------------------- ----------
.test / dev / tty ठीक है हाँ S_ISCHR
.test est test.cc / dev / tty ओके नो S_ISREG
cat test.cc | .test / dev / tty ओके नो S_ISFIFO
इको ./test | अभी / dev / tty FAIL NO S_ISREG पर

निम्नलिखित प्रोग्राम का उपयोग करके परिणाम उबंटू लिनक्स 11.04 सिस्टम से हैं:

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main() {
  char tty[L_ctermid+1] = {0};
  ctermid(tty);
  cout << "ID: " << tty << '\n';
  int fd = ::open(tty, O_RDONLY);
  if (fd < 0) perror("Could not open terminal");
  else {
    cout << "Opened terminal\n";
    struct termios term;
    int r = tcgetattr(fd, &term);
    if (r < 0) perror("Could not get attributes");
    else cout << "Got attributes\n";
  }
  if (isatty(fileno(stdin))) cout << "Is a terminal\n";
  else cout << "Is not a terminal\n";
  struct stat stats;
  int r = fstat(fileno(stdin), &stats);
  if (r < 0) perror("fstat failed");
  else {
    if (S_ISCHR(stats.st_mode)) cout << "S_ISCHR\n";
    else if (S_ISFIFO(stats.st_mode)) cout << "S_ISFIFO\n";
    else if (S_ISREG(stats.st_mode)) cout << "S_ISREG\n";
    else cout << "unknown stat mode\n";
  }
  return 0;
}

पारिभाषिक उपकरण

यदि इंटरएक्टिव सत्र को कुछ क्षमताओं की आवश्यकता होती है, तो आप टर्मिनल डिवाइस को खोल सकते हैं और (अस्थायी रूप से) सेट टर्मिनल विशेषताओं को आप की आवश्यकता होती है tcsetattr()

पायथन उदाहरण

अजगर कोड है कि फैसला करता दुभाषिया सहभागी चलाती है या का उपयोग करता है isatty()। कार्यक्रमPyRun_AnyFileExFlags()

/* Parse input from a file and execute it */

int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
                     PyCompilerFlags *flags)
{
    if (filename == NULL)
        filename = "???";
    if (Py_FdIsInteractive(fp, filename)) {
        int err = PyRun_InteractiveLoopFlags(fp, filename, flags);

कॉल Py_FdIsInteractive()

/*
 * The file descriptor fd is considered ``interactive'' if either
 *   a) isatty(fd) is TRUE, or
 *   b) the -i flag was given, and the filename associated with
 *      the descriptor is NULL or "<stdin>" or "???".
 */
int
Py_FdIsInteractive(FILE *fp, const char *filename)
{
    if (isatty((int)fileno(fp)))
        return 1;

जो कहता है isatty()

निष्कर्ष

अन्तरक्रियाशीलता के विभिन्न अंश हैं। यह जांचने के लिए कि stdinक्या पाइप / फाइल से जुड़ा है या असली टर्मिनल isatty()ऐसा करने का एक प्राकृतिक तरीका है।


6

संभवतः वे फ़ाइल के प्रकार की जांच कर रहे हैं कि "स्टडिन" fstat के साथ है, कुछ इस तरह से:

struct stat stats;
fstat(0, &stats);
if (S_ISCHR(stats.st_mode)) {
    // Looks like a tty, so we're in interactive mode.
} else if (S_ISFIFO(stats.st_mode)) {
    // Looks like a pipe, so we're in non-interactive mode.
}

बेशक पाइथन खुला स्रोत है, इसलिए आप बस यह देख सकते हैं कि वे क्या करते हैं और सुनिश्चित करने के लिए जानते हैं:

http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tar.bz2


4

विंडोज पर आप GetFileType का उपयोग कर सकते हैं।

HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD type = GetFileType(hIn);
switch (type) {
case FILE_TYPE_CHAR: 
    // it's from a character device, almost certainly the console
case FILE_TYPE_DISK:
    // redirected from a file
case FILE_TYPE_PIPE:
    // piped from another program, a la "echo hello | myprog"
case FILE_TYPE_UNKNOWN:
    // this shouldn't be happening...
}

3

स्टेट () या फ़ासत () कॉल करें और देखें कि क्या S_IFIFO को st_mode में सेट किया गया है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.