Skip to content

Instantly share code, notes, and snippets.

@alexover1
Created May 15, 2026 02:56
Show Gist options
  • Select an option

  • Save alexover1/800d76122159ed94d873ca856768bf4d to your computer and use it in GitHub Desktop.

Select an option

Save alexover1/800d76122159ed94d873ca856768bf4d to your computer and use it in GitHub Desktop.
command line utility to copy and cat files
module copy;
import stdio local;
import stdlib local;
type Opts struct {
char* from;
char* to;
}
fn Opts parseOpts(i32 argc, char** argv) {
Opts opts;
shiftArgs(&argc, &argv);
opts.from = shiftArgs(&argc, &argv);
opts.to = shiftArgs(&argc, &argv);
return opts;
}
fn char* shiftArgs(i32* argc, char*** argv) {
if (*argc == 0) return nil;
char* result = (*argv)[0];
*argv += 1;
*argc -= 1;
return result;
}
fn void copyFileFromOpts(Opts opts) {
FILE* from = stdin;
if (opts.from) {
from = fopen(opts.from, "rb");
if (from == nil) {
fatalError("file `from` cannot be read\n");
}
}
FILE* to = stdout;
if (opts.to) {
to = fopen(opts.to, "wb");
if (to == nil) {
fatalError("file `to` cannot be written\n");
}
}
copyFile(from, to);
if (opts.from) {
fclose(from);
}
if (opts.to) {
fclose(to);
}
}
fn void copyFile(FILE* from, FILE* to) {
static char[16384] buffer;
while (true) {
usize bytesRead = fread(buffer, sizeof(buffer[0]), elemsof(buffer), from);
if (bytesRead == 0) break;
fwrite(buffer, sizeof(buffer[0]), bytesRead, to);
}
}
fn void fatalError(const char* message) {
fputs(message, stderr);
exit(EXIT_FAILURE);
}
public fn i32 main(i32 argc, char** argv) {
Opts opts = parseOpts(argc, argv);
copyFileFromOpts(opts);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment