Hot answers tagged

73

Use process substitution with & redirection and exec: exec &> >(tee -a "$log_file") echo "This will be logged to the file and to the screen" $log_file will contain the output of the script and any subprocesses, and the output will also be printed to the screen. >(...) starts the process ... and returns a file representing its standard ...


35

I want to see output of first command in terminal, and save the output of the second command in a file. As long as you don't care whether what you are looking at is from stdout or stderr, you can still use tee: myscript | tee /dev/stderr | grep -P 'A|C' > out.file Will work on linux; I don't know if "/dev/stderr" is equally applicable on other *nixes.


35

When tee terminates, the command feeding it will continue to run, until it attempts to write more output. Then it will get a SIGPIPE (13 on most systems) for trying to write to a pipe with no readers. If you modify your script to trap SIGPIPE and take some appropriate action (like, stop writing output), then you should be able to have it continue after tee ...


34

The structure :w !cmd means "write the current buffer piped through command". So you can do, for example :w !cat and it will pipe the buffer through cat. Now % is the filename associated with the buffer So :w !sudo tee % will pipe the contents of the buffer through sudo tee FILENAME. This effectively writes the contents of the buffer out to the file.


28

You could use a combination of GNU stdbuf and pee from moreutils: echo "Hello world!" | stdbuf -o 1M pee cmd1 cmd2 cmd3 > output pee popen(3)s those 3 shell command lines and then freads the input and fwrites it all three, which will be buffered to up to 1M. The idea is to have a buffer at least as big as the input. This way even though the three ...


24

You could use named pipes (http://linux.die.net/man/1/mkfifo) on the command line of tee and have the commands reading on the named pipes. mkfifo /tmp/data0 /tmp/data1 /tmp/data2 cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 & command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2 When command finishes, ...


21

sometimes /dev/tty can be used for that... ls /bin /usr/bin | sort | uniq | tee /dev/tty | grep out | wc


19

I'm assuming that the pipeline of yours is running for a long time and that you are trying to remove the log file while it's running. When you delete the file, the tee process still has it open for writing, which means that the disk space is not handed back to the system. That won't happen until all open file descriptors that references the file are closed. ...


19

It's straightforward in shells that support process substitution, e.g. bash $ echo foo | tee >(xsel) foo $ xsel -o foo Otherwise, you could use a FIFO (although it lacks convenience) $ mkfifo _myfifo $ xsel < _myfifo & $ echo bar | tee _myfifo bar $ xsel -o bar [1] + Done xsel 0<_myfifo $


18

tee always writes to its standard output. If you want to send the data to a command in addition to the terminal where the standard output is already going, just use process substitution with that command. (Note that in spite of starting with >, process substitution does not redirect standard output, the tee command sees it as a parameter.) fortune | tee &...


17

You want the -a option to tee which appends rather than overwriting.


17

tee can duplicate to the current console by using tee /dev/tty git status --short | cut -b4- | tee /dev/tty | xargs gvim --remote Alteratively, you can use /dev/stdoutor /dev/stderr but they could be redirected if your command is within a script. Note that /dev/tty will always be the console (and may not exist in a non-interactive shell). This is wrong, ...


15

If I understand correctly, you're looking for the equivalent of tee file1 file2 file3, but rather than write the same data to three files file1, file2 and file3, you want to pipe the same data into three commands cmd1, cmd2 and cmd3, i.e. … | ??? cmd1 cmd2 cmd3 should be equivalent to … | cmd1 & … | cmd2 & … | cmd3 & except that … would only ...


14

From the tee manual on my system: The tee utility copies standard input to standard output, making a copy in zero or more files. The output is unbuffered. So, it reads from standard input and copies it to standard output, and while doing so also duplicates the stream into one or several files. In the following pipeline, tee would take the output ...


13

Yes, it slows things down. And it basically does have a queue of unwritten data, though that's actually maintained by the kernel—all programs have that, unless they explicitly request otherwise. For example, here is a trivial pipe using pv, which is nice because it displays transfer rate: $ pv -s 50g -S -pteba /dev/zero | cat > /dev/null 50GiB 0:00:...


13

Your assumption: fortune | tee >(?stdout?) | pbcopy won't work because the fortune output will be written to standard out twice, so you will double the output to pbcopy. In OSX (and other systems support /dev/std{out,err,in}), you can check it: $ echo 1 | tee /dev/stdout | sed 's/1/2/' 2 2 output 2 twice instead of 1 and 2. You must use other file ...


13

If you want to recover the file blocks, you need to blank the file, not unlink it: This portable way should work with most shells : : > /media/pi/KINGSTON/klima.out Unlinking the file (i.e. rm) is removing the directory entry but doesn't affect the file contents (inode) as long as the file is kept open by readers or writers.


13

The direct analogue of "tee for commands" is the pee command from moreutils (tee, but with pipes). Its arguments are used as commands to run, not as paths, and they get the input piped to them rather than written to file. All of the commands are given the standard input you piped to pee as their own. Using pee, you can get the result you wanted by telling ...


12

Your pipe commands, as a non-terminal destination, are buffering your output. It will show up eventually, but only when quite a lot of output builds up or the ping command exits. You can use ping -c 5 google.com to set a specific number of packets to be sent and then ping will exit. Your output comes back and the pipes should work as expected. Edit: ...


11

You need to give it some cache when playing from stdin cat /dev/video1 | mplayer -cache 1024 - Without that cache option you'll get the error "Seek failed Cannot seek backward in linear streams"


11

sudo tee -a /etc/ansible/hosts <myfile.txt >/dev/null Or, if you want to use cat: cat myfile.txt | sudo tee -a /etc/ansible/hosts >/dev/null Either of these should work. It is unclear how you "added" /dev/null when you tried, but this redirects the standard output of tee to /dev/null.


11

There's no difference in the sense that the data in the file will be the same if echo and tee are executed successfully and if the file is writable by the current user. The tee command would additionally produce output on its standard output, showing the text that would also be appended to the file. This would not happen in the first command. Another ...


10

Simply pipe bash to tee. Or did I misunderstand the problem? root@el6 ~ # cat test.sh date root@el6 ~ # cat test.sh | bash | tee >(logger -t "test") Wed Jul 10 23:08:03 NZST 2013 root@el6 ~ # tail -n3 /var/log/messages Jul 10 23:08:03 el6 test: Wed Jul 10 23:08:03 NZST 2013


10

It's an old post but I just found it now... Instead of redirecting the output to > /dev/null you can redirect it to the last file: echo "foobarbaz" | tee file1 > file2 Or for appending the output: echo "foobarbaz" | tee -a file1 >> file2


9

{ ... | tee /dev/fd/3 | grep -e A -e C > out.file; } 3>&1 Or with process substitution (ksh93, zsh or bash): ... | tee >(grep -e A -e C > out.file) With zsh: ... >&1 > >(grep -e A -e C > out.file)


9

The reason you are seeing the output of the original command is because tee outputs to stdout as well as the files specified. To discard this you can put >/dev/null at the end of the command or redirect this output to one of your process substitutions by adding an extra >, eg: command | tee >(sed -rn 's/.*foo (bar).*/1/p') > >(awk '{print $3}'...


9

I think I’ve figured out how to tweak your experience to turn it into something other people will be able to reproduce: $ (echo hello; sleep 1; echo world) | tee >(cat) hello hello … and, after a brief delay, world world $ echo "$?" 0 $ (echo hello; sleep 1; echo world) | tee >(echo yo) yo hello $ ...


8

You need to add stdbuf(1) into your pipeline: tail -f general.log | stdbuf -oL grep Some_word | tee -a todel.txt This will set grep's stdout stream buffering mode to be line-buffered, otherwise grep waits to get at least 4096 bytes from the stream (this is the default on Linux for buffered i/o). Alternatively, you can also call grep with --line-buffered: ...


8

In Bash, you can use process substitution with tee: tee >(grep XXX > err.log) | grep -v XXX > all.log This will put all lines matching XXX into err.log, and all lines into all.log. >( ... ) creates the process in the parentheses and connects its standard output to a pipe. This works in zsh and other modern shells too. You can also use the pee ...


8

exec >> $log_file 2>&1 && tail $log_file


Only top voted, non community-wiki answers of a minimum length are eligible