Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

The mission is to implement a cat-like program (copy all STDIN to STDOUT).


  • You may only use standard libraries
  • Indentation must be either two spaces or a single tab (in languages which require indentation)
  • Scripts must use shebangs
  • The result of cat anything.txt | ./yourprogram | diff anything.txt - should be nothing and should not be an infinite loop

Go example (84 bytes)

package main
import (
func main() {

C++ example (78 bytes)

using namespace std;
int main() {
  cout << cin.rdbuf();

Ruby example (44 bytes)

#!/usr/bin/env ruby
$stdout << $

Shortest code (by bytes) wins.

share|improve this question

marked as duplicate by Dennis Oct 30 '15 at 16:36

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

This indentation thing is nonsense – edc65 Jun 15 '14 at 12:49
The indentation rule doesn't make sense, the shebang one makes even less, because shebangs can be platform-specific, especially in the case of Python. – nyuszika7h Jun 15 '14 at 14:50
until end of June 2914… Woaah… – Qeole Jun 15 '14 at 18:03
Also, person with most implementation? What? – nyuszika7h Jun 15 '14 at 18:50
what about this python solution? for s in' /\___/\|( o o )|/ * \|\__\_/__/meow| / \| / ___ \| \/___\/'.split('|'):print s – Willem Jul 4 '14 at 15:50

37 Answers 37

GolfScript, 0 characters / bytes

This could technically be considered invalid since GolfScript will append a \n, but that can be fixed with :n; (3 bytes).

share|improve this answer
Haha, +1. Explanation for people who don't speak golfscript: stdin is read to the stack when the program starts and the stack is outputted when it ends. – Seeq Jun 15 '14 at 12:47
Nice idea, but invalid. GolfScript will append a linefeed to the input. – Dennis Jun 15 '14 at 13:55
+1 for unicorn waffles. – Martin Büttner Jun 15 '14 at 13:55
@Dennis That could be fixed in 3 bytes: :n; (edited) – Doorknob Jun 15 '14 at 14:11
I would say then that the zero-char solution is, unfortunately, invalid, and therefore the score is a solid 3. +1 nonetheless! – Jwosty Jun 16 '14 at 4:56

sed - 0 bytes

No command needed to cat a file with sed: all lines of input are printed without modification, so

sed ''

will act like cat for standard input, and

sed '' /etc/fstab

will print content of file.

share|improve this answer
"sed n" works for me and is one byte shorter. – Glenn Randers-Pehrson Aug 5 '14 at 18:04
@GlennRanders-Pehrson Yes, thank you. I didn't count the quotes as part of the sed script (I considered an empty script, something similar to sed -f /dev/null input). If we are to count chars on the line, your proposal saves a byte indeed. – Qeole Aug 5 '14 at 20:54

ΒrainFuck (5 bytes)



,  Read first byte of input and place on stack
[  While top byte is not 0...
 . Print top byte from stack as ASCII and remove
 , Read next byte of input and place on stack
]  ...loop
share|improve this answer
one of those few tasks where BF is shorter than most other things... – professorfish Jun 20 '14 at 19:54
This is less than 2 bytes (each command is 3 bits... totaling 15 bits). – Timtech Jun 23 '14 at 23:01
It is not 3 bits when stored in ASCII format, and I wrote it as ASCII. – kitcar2000 Jun 24 '14 at 14:35
This will fail on files with a null in them though.. – Claudiu Sep 10 '14 at 20:46
@Claudiu how else would you tell when the file ends? This is BF :P – VoteToSpam Dec 4 '15 at 16:28

Haskell - 17 bytes

main=interact id

id is the identity function and from the documentation :

The interact function takes a function of type String->String as its argument. The entire input from the standard input device is passed to this function as its argument, and the resulting string is output on the standard output device.

share|improve this answer

x86_64 NASM Assembly for Linux - 125 / 100

r:mov ax,0
mov di,0
mov rsi,c
mov dx,1
cmp ax,0
je e
mov di,1
jg r
e:mov ax,60
c:resw 1

I couldn't get it to fit in 100 bytes, but it is assembly. Eight bytes could be saved at the cost of changing the return status to 1 instead of 0:

r:mov ax,0
mov di,0
mov rsi,c
mov dx,1
cmp ax,0
mov di,1
jg s
mov ax,60
jg r
c:resw 1

Now, if you really want 100 bytes, here is one in exactly 100 bytes. The problem is that it doesn't exit correctly, it just segfaults:

r:mov ax,0
mov di,0
mov rsi,c
mov dx,1
cmp ax,0
mov di,1
jg r
c:resw 1

The instructions say to only use standard libraries; is there extra credit for using no libraries at all?

share|improve this answer
+1 for "no libraries" – VoteToSpam Dec 4 '15 at 16:28

C 43

share|improve this answer
You can use ~(c=getchar()) instead of (c=getchar())>=0 to save 2 characters. – nyuszika7h Jun 15 '14 at 13:59
@nyuszika7h: EOF is typically -1, but this is not guaranteed by the standard. The standard only defines about EOF in section 7.19.1: EOF which expands to an integer constant expression, with type int and a negative value, that is returned by several functions to indicate end-of-file, that is, no more input from a stream; – edc65 Jun 15 '14 at 16:11
main(){for(;putchar(getchar())<127;);} what's with that? (apparently putchar's return value is casted to int so EOF becomes 255) – bebe Jun 18 '14 at 17:54
@bebe yes it's pity. putchar get an int but truncates it to 8 bits. (It's in the spec) – edc65 Jun 18 '14 at 18:35
@edc65 VC++ error C2065: 'c':undeclared identifier. Yes, sorry my comment about putchar was incorrect. – bacchusbeale Jun 23 '14 at 19:43

Node.js 55

#!/usr/bin/env node
share|improve this answer
Could shorten by assigning p=process first to avoid repetition. Just plain #!env node works unless you've got a non-standard filesystem layout or funky $PATH stuff going on. Alternatively, drop the shebang line (so the default sh is used) and do node -e '<program>' because that's the same (6) extra number of characters and stays system-general. (If you want to join the dark side, rename your node binary to n.) Aaand drop the semicolon. – Anko Sep 15 '14 at 9:41

Perl (1)

0+1 for the -p parameter

If really the shebang counts, invoke it like this: perl -p nul on M$ or perl -p /dev/null on *nix so no shebang is involved :P

D:\>copy con
#!perl -p
        1 file(s) copied.

#!perl -p

D:\>type |
#!perl -p

share|improve this answer

Bash, 3

If you need a shebang, #!/bin/sh or #!/bin/bash is probably fine.

Had to be done. Hopelessly uncreative.


Slightly more interesting:


Normally, tee FILENAME sends its input both to the file and to standard output. Without an argument, it seems to behave like cat.

Bash, 2

...if you don't mind the status message at the end and the fact that the output only comes after EOF on standard input!


Removing the status message costs 4 chars for a total of 6 chars:

dd 2>a

The message is sent to the file a instead of standard output.

If you dispose of the message entirely, the total length is 14 7:

dd 2>&-

Bash/SHELF, 1

For the shebang, try


where is the location of your SHELF file.

SHELF is my PYG-like golfing library for Bash.


D just aliases to cat. Also uncreative.

And the alias for tee is...

share|improve this answer
2>&- is shorter than 2>/dev/null. – nyuszika7h Jun 26 '14 at 11:35

Linux/Unix tools, 16 bytes

grep $

Other tools that work when called by bash/sh are

tr . .

and (15 bytes)

sed n

EDIT: Changed title from "bash/sh" to "Linux/Unix tools" because although the tools can be called by bash or sh they aren't actually part of bash or sh.

share|improve this answer
Copies the indentation? – Seeq Jun 15 '14 at 12:54
@TheRare yes. It copies "all stdin to the stdout," as required. I guess that the 2-space indentation requirement refers to indentation of the code. – Glenn Randers-Pehrson Jun 15 '14 at 12:59
Yes, yes it does. – Seeq Jun 15 '14 at 13:01
shebangs don't count towards your score (and why are they #!/bin/sh? that isn't bash) – professorfish Jun 18 '14 at 16:35
@professorish /bin/sh is Bash on my platform (Ubuntu 14.04) Perhaps I should have said Ubuntu and RedHat Fedora in my answer instead of "many systems" (will edit accordingly). In the example for ruby shown in the question, the shebang is counted among the 44 bytes. – Glenn Randers-Pehrson Jun 18 '14 at 16:47

CJam - 1


No extra newline :)

share|improve this answer

AWK - ???

The complete program in awk has only 1 char:


Unluckily the shebang stuff lets kinda explode it's length :(

#!/usr/bin/awk -f

May I copy awk into the filesystem root? >;-)

As oneliner it is shorter:

$ awk 1 </etc/hostname 

I'm not sure what counts and what not...

share|improve this answer
In my experience, code in codegolf doesn't use shebangs, it is intended to be directly executed by the interpreter (awk in this case). – Ramchandra Apte Jun 15 '14 at 13:42
Thinking about stdout = g(f(stdin))... <input tac|tac >output fails if the last input line has no linefeed. I like <input rev|rev >output. So far for f = g. What comes into the game for f != g? tr and it's inverse? sed and backwards? Smells not really promising... – yeti Jun 17 '14 at 14:59
A flash of enlightenment hit me: tee ftw!!! :) – yeti Jun 18 '14 at 14:35
At least in OpenBSD, printf 'full\0string' | awk 1 outputs 'full\n', so it is not perfect. I wonder if gawk or mawk does better? – kernigh Jun 20 '14 at 21:01

16 bit .com binary for MSDOS - 31 Bytes (112 Byte NASM Source)

00 00 BA 00 00 B9 01 00 B4 3F BB 00 00 CD 21 83 F8 00 74 09 B4 40 BB 01 00 CD 21 EB EB CD 20

The nasm source code:

c:resw 1
mov dx,c
mov cx,1
mov ah,63
mov bx,0
int 33
cmp ax,0
je e
mov ah,64
mov bx,1
int 33
jmp r
int 32

Build with "nasm -f bin -o cat-msdos.s".

I already provided a solution for x86_64 Linux, but was unable to get it under 100 bytes. This is over 100 bytes of assembly, but the actually binary is only 31 bytes! This must be the simplest solution here.

share|improve this answer

Ruby, 2 bytes (or 1?)

#!/usr/bin/env ruby -p

The question states that the shabang needs to be included. The 2 bytes counted is the -p part of the shebang. The otherwise empty script makes Ruby behave exactly likes cat when run with the p switch: Run it without arguments and it will take input from stdin, or with arguments and it print the contents of those files.


Ruby, 8 bytes

@core1024 had already posted a solution in Perl similar to the one above, so here is another attempt. Note that the following are not scripts, they are Ruby programs ;)

puts *$<

Ruby, 16 bytes

I think this one is cute

print while gets
share|improve this answer

Python 2.x - 56 or 61 bytes

Input limited to 10^9 bytes.

from os import*

Or for infinite input (61 bytes):

from sys import*

Not much to say, is there?

share|improve this answer
This isn't cat because it adds a linefeed or whatever your system uses (cr+lf?) to the output. – yeti Jun 15 '14 at 13:29
@yeti You're right. I use Windows atm, so couldn't remember that. Fixing... – Seeq Jun 15 '14 at 13:39
@yeti Better now? – Seeq Jun 15 '14 at 13:56
You can use 1e9 instead of 10**9 to save 2 characters. Also, the shebang doesn't count towards character count. – nyuszika7h Jun 15 '14 at 14:02
@nyuszika7h That prints an extra space. – Seeq Jun 15 '14 at 15:05

Batch (8)

type CON

Type writes file content to the console and CON is treated as a file containing all console input.

share|improve this answer
I like how this has a one-to-one correspondence with Bash: type to cat, con to /dev/stdin – VoteToSpam Dec 4 '15 at 16:33

Common Lisp

ECL, 106

#!/usr/local/bin/ecl -shell
(ignore-errors(loop(write-byte(read-byte *standard-input*)*standard-output*)))

SBCL, 109

#!/usr/local/bin/sbcl --script
(ignore-errors(loop(write-byte(read-byte *standard-input*)*standard-output*)))

CLISP, 188 180

(let((i(make-stream 0 :element-type'(mod 256)))(o(make-stream 1
:direction :output :element-type'(mod
256))))(ignore-errors(loop(write-byte(read-byte i)o))))

These are the shortest programs that I can make, yet none are under 100 bytes.

The main problem is that *standard-input* and *standard-output* are character streams, not byte streams. A simple (loop(write-char(read-char)) would copy the characters but would fail to preserve bytes that did not form valid characters. Now my Common Lisp implementations want to use UTF-8 (perhaps because my locale is UTF-8), but I want to copy binary files that my not be valid UTF-8. Therefore I must copy bytes, not characters.

In ECL and SBCL, standard input and output are bivalent for both bytes and characters. I may use read-byte and write-byte, but those functions lack default streams, so I must pass *standard-input* and *standard-output* as arguments.

CLISP insists that *standard-input* and *standard-output* transport only characters. The way around this is to call ext:make-stream on file descriptor 0 (standard input) and file descriptor 1 (standard output) to make binary streams.

All three programs loop byte by byte. This is a slow way to copy bytes. A faster way would use a vector of 16384 bytes with read-sequence and write-sequence, but the program would be longer.

share|improve this answer

zsh, 15 bytes


Note that there is no newline at the end of the file.

share|improve this answer

Some Perl:


25 bytes with shebang. This can also be much smaller with die(), and by bending the rules ever so slightly:


Executing the 4th test could only be done like this:

cat bla|perl ./perlcat 2>&1|diff bla -

<> is an abbreviation for <STDIN>. The 25 byte print example is pretty self explanatory. die() is normally used for exiting non-zero and outputting an error message, hence using the 2>&1 to bend the rules around the 4th test.

It also appears that the semicolon is not required for the last statement in Perl, so the first example could be brought down to 24 bytes.

share|improve this answer

Perl6 (14):

.say for lines

And, if it doesn't need to be deterministically printing it in the correct order (hehe), you can use the auto-threading "map-apply"

share|improve this answer

><>, 7 bytes

I know a ><> solution already exists, but I figured it would be welcome.


Click here to try it

share|improve this answer

Java 68 104

My first approach at this:

class a{public static void main(String[]a){System.out.print(a[0]);}}

EDIT: Yeah, I misunderstood the concept, here is another attempt, I couldn't get it done in less than 100 chars so I'd appreciate any suggestion:

class a{public static void main(String[]a)throws Exception{for(;;)System.out.write(;}}
share|improve this answer
That's not how cat works. cat displays the contents of the file(s) given as command line arguments, or takes input from stdin when there are no arguments. – daniero Jun 24 '14 at 23:16
@daniero Yeah I wasn't right, it works now, although much longer. – BrunoJ Jun 25 '14 at 18:33
This breaks the rule about looping forever, how about: class a{public static void main(String[]a)throws Exception{int r;while(0<(;}} – Roy van Rijn Sep 15 '14 at 11:29


While 1:Input Str1:Disp Str1:End
share|improve this answer
Use "Str1" instead of "A". – Cᴏɴᴏʀ O'Bʀɪᴇɴ Oct 28 '15 at 5:01
@CᴏɴᴏʀO'Bʀɪᴇɴ Thanks for the tip, I was really bad at TI-Basic a year ago. Only problem is you can't use the STO-> arrow but you couldn't before either. It seems so silly that I used A instead of a string var :P again, thanks for the tip! – Timtech Oct 29 '15 at 0:46
@ThomasKwa Good idea. – Timtech Oct 29 '15 at 21:39

GML, 37

share|improve this answer

Rust - 74

Really generic...

use std::io;fn main(){for l in io::stdin().lines(){io::print(l.unwrap())}}

No Comment - 12


Unimplemented, so, yeah.

share|improve this answer

Dart - 48

share|improve this answer

Groovy - 45 bytes

#!/usr/bin/env groovy
System.out <<

And test:

$ cat FirstJsonObj.groovy | ./Cats.groovy | diff FirstJsonObj.groovy  -
share|improve this answer

Tcl 57

#!/usr/bin/env expect
while {[gets stdin d]>=0} {puts $d}
share|improve this answer

Swift, 32

while let l=readLine(){print(l)}

Prints every line until EOF is reached

If you're really picky that this doesn't work with an empty line at the end or whatever you can use this:

while let l=readLine(stripNewline:false){print(l,terminator:"")}
share|improve this answer

MATLAB, 18 bytes


Cannot use disp as it appends a newline to the output.

share|improve this answer

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