There's no one OS that's best for all purposes, so I avoid tying my work to any one platform. Unfortunately for me, almost everything about computers is still platform-specific. The obvious case is applications: even though essentially every home computer can run x86 code, no common subset of APIs, ABIs, and executable formats have become standard. Even more disappointing is how platform-specific basic user-level operations are: the simplest computing tasks (copy a file, run a program, create an archive, etc.) are all platform-specific as well.

A common solution for scripted tasks is to use a build system. I won't pick on any particular build system, but I haven't encountered any that make even basic things easy. Consider a simple task: copying a file to an output directory. What I want to write is something like copy source destination. Instead, many systems still require platform-specific commands (e.g. choosing to invoke cp or xcopy from the build script), plus a hierarchy of rules to make the operation fit into a dependency tree.

None of these systems make my hobby work more enjoyable, as I simply want to run a sequence of operations, halting if any fail. Whether typing individual one-off commands, or scripting a massive server deployment, I don't want to manually translate commands for each platform. I'd rather have a simple interface with a fraction of the functionality, but have it be consistent everywhere I work.

Thankfully, the standard libraries provided with most modern languages provide this abstraction already (e.g. file I/O APIs that work across platforms); they're just not exposed in a simple shell/scripting interface. A very thin wrapper over these APIs makes for a fine basic scripting environment.

The application I'll make is a simple command runner — run. The commands it supports are unabashedly simple (copy, delete etc.), but they're consistent on every platform. No need for build hierarchies, and no .sh or .bat files in each project root. Furthermore, the interpreter is written in the same language as all my other code, so it's guaranteed to work on any platform my code can target, without a need to install python or java just to run a script.

There's not much technically impressive here; run simply reads lines of text and passes them to the appropriate standard library function. This simplicity makes adding new commands trivial. In fact, I'd bet it's faster to add case "copy": std::fs::copy(...) than it is to search stackoverflow for how to write build-system rules to copy a file in a platform-independent manner.

Overall, it's nothing special, but I encourage you to try skipping the usual suspects when setting up builds for hobby work. It takes surprisingly little work, and maybe, together, we can prevent another build.bat from coming into existence.

			⌨771 l ⌨100 s ⌨135 ⏎
			␤ ⎙11 a.txt⏎
			␤ ⌨884 c ⌨67 a ⌨151 t ⌨87   ⌨109 . ⌨52 / ⌨97 d ⌨124 e ⌨57 m ⌨52 o ⌨359 ⏎
			␤ ⎙18 copy a.txt b.txt⏎
			␤ ⌨1133 r ⌨92 u ⌨146 n ⌨77   ⌨223 . ⌨65 / ⌨77 d ⌨141 e ⌨75 m ⌨60 o ⌨394 ⏎
			␤ ⎙18  ⌨1021 l ⌨78 s ⌨209 ⏎
			␤ ⎙18 a.txt⏎
			␤ ␃
< Find more posts at