Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.
echo '<h1>hello, world</h1>' |  firefox
cat index.html | firefox

These commands don't work.
If firefox can read stdin, I can send html to firefox via pipe.
Is it possible to make firefox read stdin?

share|improve this question
1  
What exactly you want to accomplish? –  pbm Nov 19 '11 at 9:07
2  
@pbm: It might be useful to avoid storing temporary data... –  l0b0 Feb 2 '12 at 10:39

6 Answers 6

up vote 16 down vote accepted

The short answer is, you're better off writing a temporary file and opening that. Getting pipes to work properly is more complicated and probably won't give you any extra advantages. That said, here's what I've found.

If your firefox command is actually starting Firefox instead of talking with an already-running Firefox instance, you can do this:

echo '<h1>hello, world</h1>' | firefox /dev/fd/0

Which tells Firefox explicitly to read its standard input, which is where the pipe is putting its data. But if Firefox is already running, the firefox command is just going to pass that name to the main Firefox process, which will read its own standard input, which probably won't give it anything and certainly isn't connected to your pipe.

Furthermore, when reading from a pipe, Firefox buffers things pretty heavily, so it's not going to update the page each time you give it a new line of HTML, if that's what you're going for. Try closing Firefox and running:

cat | firefox /dev/fd/0

(N.B. you do actually need the cat here.) Paste some long lines into your shell window repeatedly until Firefox decides to update the page, and you can see how much data it takes. Now send an End-Of-File signal by hitting Ctrl+D on a new line, and watch Firefox update instantly. But then you can't add any more data.

So best is probably:

echo '<h1>hello, world</h1>' >my_temporary_file; firefox my_temporary_file
share|improve this answer

You can use data URIs, like this:

echo '<h1>hello, world</h1>' |firefox "data:text/html;base64,$(base64 -w 0 <&0)"

&0 is the file descriptor for stdin, so it encodes stdin to base64, then interpolates that into the data URI.

The same trick works for other browsers, too:

echo '<h1>hello, world</h1>' |chromium "data:text/html;base64,$(base64 -w 0 <&0)"
echo '<h1>hello, world</h1>' |opera    "data:text/html;base64,$(base64 -w 0 <&0)"

If you want, you can put the second part in a bash script (I'll call it pipefox.sh):

#!/bin/bash
firefox "data:text/html;base64,$(base64 -w 0 <&0)"

Now you can do:

echo '<h1>hello, world</h1>' |pipefox.sh
share|improve this answer
    
totally awesome!, How the hell did you came up with this?. You can improve pipefox.sh renaming to pipebrowser with context: $1 "data:text/html;base64,$(base64 -w 0 <&0)" allowing to choose the browser to your liking –  albfan Apr 22 at 22:24
    
&0 is the file descriptor for stdin, so it encodes stdin to base64, then interpolates that into the data URI. –  Snowball Apr 23 at 10:22

You can use process substitution:

 firefox <( echo '<h1>hello, world</h1>' )

 firefox <( cat page_header.html contents.html footer.html )

 firefox  <( echo "<h1>Hello number "{1..23}"!</h1>" )
share|improve this answer
    
Can't get these to work with Ubuntu 14.04 using bash and Firefox 29.0 –  John S Gruber May 7 at 22:07

I wrote a python script to write stdin to a temporary file and then open the temporary file with Firefox.

#!/usr/bin/env python
import sys
import tempfile
import subprocess

with tempfile.NamedTemporaryFile() as f:
  f.write(sys.stdin.read())
  f.flush()
  process = subprocess.Popen(['firefox', f.name])
  process.wait()
share|improve this answer

Look what searching for 'browser stdin' turned up!, a nice little shell script:

#!/bin/sh

# read from stdin, write to a temp file, open the temp file in a browser, then delete it
tmpfile=$(tempfile); cat > $tmpfile; x-www-browser $tmpfile; rm $tmpfile

If you save this in stdin2www, make it executable (chmod +x stdin2www), your examples should work via cat index.html | ./stdin2www. Just note that relative links, images, etc, will fail since the page that will be opened is something /tmp/; more work would be needed to fix this.

share|improve this answer

I found this:

bcat -- pipe to browser utility

... to install on Ubuntu Natty, I did:

sudo apt-get install rubygems1.8
sudo gem install bcat
# to call
ruby -rubygems /var/lib/gems/1.8/gems/bcat-0.6.2/bin/bcat
echo "<b>test</b>" | ruby -rubygems /var/lib/gems/1.8/gems/bcat-0.6.2/bin/bcat

I thought it works with its own browser - but running the above opened a new tab in an already running Firefox, pointing at a localhost address http://127.0.0.1:53718/btest ... With bcat installation you can also do:

tail -f /var/log/syslog | ruby -rubygems /var/lib/gems/1.8/gems/bcat-0.6.2/bin/btee

... a tab will again open, but Firefox will keep showing the loading icon (and apparently would update the page when syslog updates).

The bcat homepage also references the uzbl browser, which can apparently handle stdin - but for its own commands (should probably look into this more, though)


EDIT: As I needed something like this badly (mostly to view HTML tables with data generated on the fly (and my Firefox is getting really slow to be useful with bcat), I tried with a custom solution. Since I use ReText, I already had installed python-qt4 and WebKit bindings (and dependencies) on my Ubuntu. So, I put together a Python/PyQt4/QWebKit script - which works like bcat (not like btee), but with its own browser window - called Qt4WebKit_singleinst_stdin.py (or qwksisi for short):

Basically, with the downloaded script (and dependencies) you can alias it in a bash terminal like this:

$ alias qwksisi="python /path/to/Qt4WebKit_singleinst_stdin.py"

... and in one terminal (after aliasing), qwksisi will raise the master browser window; while in another terminal (again after aliasing), one could do the following to obtain stdin data:

$ echo "<h1>Hello World</h1>" | qwksisi - 

... as shown below:

qwksisi

Don't forget the - at end to refer to stdin; otherwise a local filename can be used as last argument, as well.

Basically, the problem here is to solve:

  • single instance problem (so first run of script becomes a "master" and raises a browser window - while subsequent runs simply pass data to master and exit)
  • interprocess communication for sharing variables (so exiting processes can pass data to the master browser window)
  • Timer update in the master that checks for new content, and updates the browser window if new content arrived.

As such, the same could be implemented in, say, Perl with Gtk bindings and WebKit (or other browser component). I wonder, though, if the XUL framework by Mozilla could be used to implement the same functionality - I guess in that case, one would work with the Firefox browser component.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.