Take the 2-minute tour ×
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.

The mission is to implement a cat-like program (copy all stdin to stdout) in less than 100 bytes of code.

Rules:

  • 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 (
  "os"
  "io"
)
func main() {
  io.Copy(os.Stdout,os.Stdin)
} 

C++ example (78 bytes)

#include<iostream>
using namespace std;
int main() {
  cout << cin.rdbuf();
}

Ruby example (44 bytes)

#!/usr/bin/env ruby
$stdout << $stdin.read

Shortest code (by bytes) wins.

share|improve this question
31  
This indentation thing is nonsense –  edc65 Jun 15 at 12:49
3  
@ProgramFOX Stoning the Rosetta. –  Sieg Jun 15 at 12:53
6  
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 at 14:50
4  
until end of June 2914… Woaah… –  Qeole Jun 15 at 18:03
4  
Also, person with most implementation? What? –  nyuszika7h Jun 15 at 18:50

29 Answers 29

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
5  
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. –  Sieg Jun 15 at 12:47
2  
Nice idea, but invalid. GolfScript will append a linefeed to the input. –  Dennis Jun 15 at 13:55
4  
+1 for unicorn waffles. –  Martin Büttner Jun 15 at 13:55
1  
@Dennis That could be fixed in 3 bytes: :n; (edited) –  Doorknob Jun 15 at 14:11
1  
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 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 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 at 20:54

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

ΒrainFuck (5 bytes)

,[.,]

Explanation:

,  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
1  
one of those few tasks where BF is shorter than most other things... –  professorfish Jun 20 at 19:54
    
This is less than 2 bytes (each command is 3 bits... totaling 15 bits). –  Timtech Jun 23 at 23:01
2  
It is not 3 bits when stored in ASCII format, and I wrote it as ASCII. –  kitcar2000 Jun 24 at 14:35

C 43

main(c){while((c=getchar())>=0)putchar(c);}
share|improve this answer
3  
You can use ~(c=getchar()) instead of (c=getchar())>=0 to save 2 characters. –  nyuszika7h Jun 15 at 13:59
1  
@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 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 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 at 18:35
    
@edc65 VC++ error C2065: 'c':undeclared identifier. Yes, sorry my comment about putchar was incorrect. –  bacchusbeale Jun 23 at 19:43

x86_64 NASM Assembly for Linux - 125 / 100

r:mov ax,0
mov di,0
mov rsi,c
mov dx,1
syscall
cmp ax,0
je e
mov di,1
syscall
jg r
e:mov ax,60
syscall
SECTION .bss
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
syscall
cmp ax,0
mov di,1
jg s
mov ax,60
s:syscall
jg r
SECTION .bss
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
syscall
cmp ax,0
mov di,1
syscall
jg r
SECTION .bss
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

Linux/Unix tools, 16 bytes

#!/bin/sh
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
1  
Copies the indentation? –  Sieg Jun 15 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 at 12:59
1  
Yes, yes it does. –  Sieg Jun 15 at 13:01
    
shebangs don't count towards your score (and why are they #!/bin/sh? that isn't bash) –  professorfish Jun 18 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 at 16:47

Node.js 55

#!/usr/bin/env node
process.stdin.pipe(process.stdout);
share|improve this answer

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 cat.pl
#!perl -p
^Z
        1 file(s) copied.

D:\>type cat.pl
#!perl -p

D:\>type cat.pl | cat.pl
#!perl -p

D:\>
share|improve this answer

AWK - ???

The complete program in awk has only 1 char:

1

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

#!/usr/bin/awk -f
1

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

As oneliner it is shorter:

$ awk 1 </etc/hostname 
darkstar

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

share|improve this answer
5  
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 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 at 14:59
    
A flash of enlightenment hit me: tee ftw!!! :) –  yeti Jun 18 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 at 21:01

Python 2.x - 56 or 61 bytes

Input limited to 10^9 bytes.

#!/usr/bin/python
from os import*
write(1,read(0,10**9))

Or for infinite input (61 bytes):

#!/usr/bin/python
from sys import*
stdout.write(stdin.read())

Not much to say, is there?

share|improve this answer
1  
This isn't cat because it adds a linefeed or whatever your system uses (cr+lf?) to the output. –  yeti Jun 15 at 13:29
    
@yeti You're right. I use Windows atm, so couldn't remember that. Fixing... –  Sieg Jun 15 at 13:39
    
@yeti Better now? –  Sieg Jun 15 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 at 14:02
1  
@nyuszika7h That prints an extra space. –  Sieg Jun 15 at 15:05

CJam - 1

q

No extra newline :)

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.

cat

Slightly more interesting:

tee

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!

dd

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

#!/bin/sh
. shelf.sh

where shelf.sh is the location of your SHELF file.

SHELF is my PYG-like golfing library for Bash.

D

D just aliases to cat. Also uncreative.

And the alias for tee is...

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

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
r:
mov ah,63
mov bx,0
int 33
cmp ax,0
je e
mov ah,64
mov bx,1
int 33
jmp r
e:
int 32

Build with "nasm -f bin -o cat.com 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.

edit:

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

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

TI-BASIC, 26

While 1:Input A:Disp A:End
share|improve this answer

GML, 37

while(1)show_message(keyboard_string)
share|improve this answer

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

#!/usr/local/bin/clisp
(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

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(System.in.read());}}
share|improve this answer
1  
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 at 23:16
1  
@daniero Yeah I wasn't right, it works now, although much longer. –  BrunoJ Jun 25 at 18:33

Shell script, 11 bytes (including shebang)

#!/bin/cat
share|improve this answer
    
XD somehow my cat was on /usr/bin/cat XD –  Kokizzu Jun 26 at 10:15
    
This isn't technically a shell script, it's a cat script. The shell isn't involved for executables with a shebang, unless the shebang happens to point to the shell. –  nyuszika7h Jul 2 at 18:20
    
@nyuszika7h Arguably it's a shell script that's just using cat as the shell. –  fluffy Jul 3 at 5:06
    
But this is not a cat program. This is a quine. –  user23013 Jul 4 at 8:18
    
@user23013 Oh, so it is. –  fluffy Jul 5 at 5:46

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

import"dart:io";main(){stdout.addStream(stdin);}
share|improve this answer

Groovy - 45 bytes

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

And test:

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

zsh, 15 bytes

#!/bin/zsh
1<&1

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

share|improve this answer

C# 77

static void Main(string[] a){foreach(string s in a) {Console.Write(s+" ");}}
share|improve this answer
3  
i could not verify this, doesn't this like echo not cat ? –  Kokizzu Jun 24 at 1:21

grep - 2 or 7 bytes

grep ''

Tested on Linux.

The "program" of '' is two bytes but the complete command is 7 bytes.

share|improve this answer
    
Actually, '' as a grep program won't work (try printf "#!/bin/grep\n''" > prog; chmod +x prog; ./prog). In your example, '' is just shell quote syntax. I can't see a way to run this with grep as interpreter, so this should count as a 7-byte shell script. –  nyuszika7h Jul 2 at 18:14
    
'' as a program will work from the interactive shell: "seq 100 | grep '' | md5sum" produces the same result as "seq 100 | md5sum" (ignore the double quotes) –  Ken A Jul 2 at 18:52

Many languages (49)

print("\\    /\\\n )  ( \')\n(  /  )\n \\(__)|");

Because :3 is more like a tame lion.

share|improve this answer
1  
That's not what the question is asking for, although it sounds like it :) –  aditsu Jun 25 at 9:22
    
I couldn't resist! –  Mardoxx Jun 26 at 12:16

Ruby, 21 characters

#!/usr/bin/env ruby
while 1;puts gets;end
share|improve this answer
1  
but it won't stop '___' –  Kokizzu Jul 1 at 2:15
    
testing command: cat anything.txt | ./cat.rb –  Kokizzu Jul 1 at 2:16
    
neither will cat –  fogcityben Jul 1 at 21:23

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.