Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I use this script, saved as `rerun`, to automatically re-execute a command whenever a file in the current directory changes:

    #!/usr/bin/sh

    while true; do
        reset;
        "$@";
        inotifywait -e MODIFY --recursive .
    done
For example, if you invoke `rerun make test` then `rerun` will run `make test` whenever you save a file in your editor.



There's also modd[0] which allows for many file watch pattern -> command combos to easily be defined & run simultaneously from a modd.conf file.

[0]https://github.com/cortesi/modd


I have two similar commands, both written as zsh functions but easily adaptable to shell scripts, other shells, etc.

# wait on a path and do something on change, e.g. `wait_do test/ run_tests.sh`

    wait_do() {
        local watch_file=${1}
        shift

        if [[ ! -e ${watch_file} ]]; then
            echo "${watch_file} does not exist!"
            return 1
        fi

        if [[ `uname` == 'Linux' ]] && ! command -v inotifywait &>/dev/null; then
            echo "inotifywait not found!"
            return 1
        elif [[ `uname` == 'Darwin' ]] && ! command -v fswatch &>/dev/null; then
            echo "fswatch not found, install via 'brew install fswatch'"
            return 1
        fi

        local exclude_list="(\.cargo-lock|\.coverage$|\.git|\.hypothesis|\.mypy_cache|\.pgconf*|\.pyc$|__pycache__|\.pytest_cache|\.log$|^tags$|./target*|\.tox|\.yaml$)"
        if [[ `uname` == 'Linux' ]]; then
            while inotifywait -re close_write --excludei ${exclude_list} ${watch_file}; do
                local start=$(\date +%s)
                echo "start:    $(date)"
                echo "exec:     ${@}"
                ${@}
                local stop=$(\date +%s)
                echo "finished: $(date) ($((${stop} - ${start})) seconds elapsed)"
            done
        elif [[ `uname` == 'Darwin' ]]; then
            fswatch --one-per-batch --recursive --exclude ${exclude_list} --extended --insensitive ${watch_file} | (
                while read -r modified_path; do
                    local start=$(\date +%s)
                    echo "changed:  ${modified_path}"
                    echo "start:    $(date)"
                    echo "exec:     ${@}"
                    ${@}
                    local stop=$(\date +%s)
                    echo "finished: $(date) ($((${stop} - ${start})) seconds elapsed)"
                done
            )
        fi
    }

# keep running a command until successful (i.e. zero return code), e.g. `nevergonnagiveyouup rsync ~/folder/ remote:~/folder/`

    nevergonnagiveyouup() {
        false
        while [ $? -ne 0 ]; do
            ${@}

            if [ $? -ne 0 ]; then
                echo "[$(\date +%Y.%m.%d_%H%M)] FAIL: trying again in 60 seconds..."
                sleep 60
                false
            fi
        done
    }




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: