50 short programs in Rust, #5 - symlinks

March 14, 2020

I can almost never remember how to create symlinks - that is, which way round the arguments to 'ln' go. So I wrote a Rust equivalent, called symlink, which you invoke as symlink file-a --pointing-to file-b - more characters, but if I don't have to look it up every time, quicker overall.

Here's the code:

use clap::{App, Arg};
use std::io::{Error, ErrorKind};
use std::os::unix::fs;
use std::path::Path;

fn main() -> std::io::Result<()> {
    let matches = App::new("symlink")
        .about("'ln' replacement that's more intuitive")
                .help("Existing file for symlink to point to")
                .help("Symlink file to create")

    let symlink = Path::new(matches.value_of("LINK").unwrap());
    let pointing_to = Path::new(matches.value_of("pointing-to").unwrap());

    // Convert the source file from a relative to absolute path if necessary.
    let mut path = std::env::current_dir()?;
    let src_file = if pointing_to.is_absolute() {
    } else {

    if symlink.exists() {
            format!("{} already exists", symlink.display()),
    } else if !src_file.exists() {
            format!("{} does not exist", src_file.display()),
    } else {
        fs::symlink(src_file, symlink)

and here it is in action:

$ symlink ~/.local/bin/code --pointing-to ~/.local/VSCode-linux-x64/bin/code

$ file ~/.local/bin/code
/home/rkd/.local/bin/code: symbolic link to /home/rkd/.local/VSCode-linux-x64/bin/code

$ symlink ~/.local/bin/code --pointing-to ~/.local/VSCode-linux-x64/bin/code 
Error: Custom { kind: AlreadyExists, error: "/home/rkd/.local/bin/code already exists" }

$ symlink ~/.local/bin/code3 --pointing-to /nowhere                         
Error: Custom { kind: NotFound, error: "/nowhere does not exist" }