Hello, forum :)

Does anyone know a c++ code that performs the same actions as a "tee" command does in linux? Basically what the tee command does is read an input from an input stream and directs it to two places:
1) Displays the input stream on the screen
2) Saves the input stream to a specified file
The documentation for a tee command can be found here. In that example, the tee command performs one more action: word count. I am not so worried about implementing this into my code; I just want to be able to read in all the text files and display it on the screen as well as save it to another text file.

Any suggestions would be great.

Thanks.

Recommended Answers

All 3 Replies

Did you hear about <fstream> class from the standart library.

It defines some basic file input/output operations for binary and text files, but you have to give the file names to the program, there is no folder manipulating operations defined in this class.

Unix tee is a filter which reads from stdin and in addition to piping the input to stdout also copies it into a file.

In C++, we can generalize the idea to a reusable component. Create a user-defined ostream that can send its output to two output streams. tee is then just a special case; read input from stdin and send output to stdout and a std::ofstream.

#include <iostream>

template < typename CHAR_TYPE,
           typename TRAITS_TYPE = std::char_traits<CHAR_TYPE> >
struct basic_teebuf : public std::basic_streambuf< CHAR_TYPE, TRAITS_TYPE >
{
    typedef std::basic_streambuf< CHAR_TYPE, TRAITS_TYPE > streambuf_type ;
    typedef typename TRAITS_TYPE::int_type int_type ;

    basic_teebuf( streambuf_type* buff_a, streambuf_type* buff_b )
            : first(buff_a), second(buff_b) {}

    protected:
        virtual int_type overflow( int_type c )
        {
            const int_type eof = TRAITS_TYPE::eof() ;
            if( TRAITS_TYPE::eq_int_type( c, eof ) )
                return TRAITS_TYPE::not_eof(c) ;
            else
            {
                const CHAR_TYPE ch = TRAITS_TYPE::to_char_type(c) ;
                if( TRAITS_TYPE::eq_int_type( first->sputc(ch), eof ) ||
                    TRAITS_TYPE::eq_int_type( second->sputc(ch), eof ) )
                        return eof ;
                else return c ;
            }
        }

        virtual int sync()
        { return !first->pubsync() && !second->pubsync() ? 0 : -1 ; }

    private:
        streambuf_type* first ;
        streambuf_type* second ;
};

template < typename CHAR_TYPE,
           typename TRAITS_TYPE = std::char_traits<CHAR_TYPE> >
struct basic_teestream : public std::basic_ostream< CHAR_TYPE, TRAITS_TYPE >
{
    typedef std::basic_ostream< CHAR_TYPE, TRAITS_TYPE > stream_type ;
    typedef basic_teebuf< CHAR_TYPE, TRAITS_TYPE > streambuff_type ;

    basic_teestream( stream_type& first, stream_type& second )
         : stream_type( &stmbuf ), stmbuf( first.rdbuf(), second.rdbuf() ) {}

    private: streambuff_type stmbuf ;
};

typedef basic_teebuf<char> teebuf ;
typedef basic_teestream<char> teestream ;

A dumbed down (no error handling, parsing and processing of command line switches etc.) program to use a teestream to implement the tee command:

#include <fstream>

int main( int argc, const char** argv )
{
    std::ofstream file( argv[1] ) ;
    teestream teeout( std::cout, file ) ;
    teeout << std::cin.rdbuf() ;
}

use it this way:
compile > g++ -Wall -std=c++98 -pedantic -Werror -ominimaltee and run > cat *.cc | grep #include | wc -l | ./minimaltee count.txt

commented: You're sick. But in a good way :) +16

thanks!!

Okay, then now my next question is this: "How do I run this c++ code using GNU Tools? I've been reading about GNU Tools but it's not making much sense...thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.