# “cat”-like program [duplicate]

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

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.

• 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

# 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).

• 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. – seequ 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
• @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.

• "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)

,[.,]


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

• one of those few tasks where BF is shorter than most other things... – user16402 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 – clapp Dec 4 '15 at 16:28

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.

# 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?

# C 43

main(c){while((c=getchar())>=0)putchar(c);}

• 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
process.stdin.pipe(process.stdout);

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

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

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

D:\>


# 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

• 2>&- is shorter than 2>/dev/null. – nyuszika7h Jun 26 '14 at 11:35

## 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. • Copies the indentation? – seequ 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. – seequ Jun 15 '14 at 13:01 • shebangs don't count towards your score (and why are they #!/bin/sh? that isn't bash) – user16402 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 q  No extra newline :) # 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...

• 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... – user19214 Jun 17 '14 at 14:59
• A flash of enlightenment hit me: tee ftw!!! :) – user19214 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
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.

# 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 ;)

$ # Tcl 57 #!/usr/bin/env expect while {[gets stdin d]>=0} {puts$d}


# 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:"")}


# MATLAB, 18 bytes

fprintf(input(''))


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