Skip to content

Instantly share code, notes, and snippets.

@crasm
Last active May 5, 2025 01:08
Show Gist options
  • Select an option

  • Save crasm/41b5b11111d2f2419b31da159fa77447 to your computer and use it in GitHub Desktop.

Select an option

Save crasm/41b5b11111d2f2419b31da159fa77447 to your computer and use it in GitHub Desktop.

Revisions

  1. crasm revised this gist Sep 10, 2023. 1 changed file with 8 additions and 6 deletions.
    14 changes: 8 additions & 6 deletions gguf-merge.sh
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,5 @@
    #!/bin/sh

    set -e

    log() {
    format="$1"; shift
    # shellcheck disable=SC2059
    @@ -28,7 +26,12 @@ EOF
    # This is called by an interrupt
    # shellcheck disable=SC2317
    cleanup() {
    log "Interrupted..."
    if [ -n "$1" ]; then
    log "$@"
    else
    log 'Interrupted...'
    fi

    if [ -w "$split_a" ] && [ -n "$split_a_size" ]; then
    log 'Truncating "%s" to original size: %s bytes\n' "$split_a" "$split_a_size"
    truncate -c -s "$split_a_size" "$split_a"
    @@ -91,11 +94,10 @@ shift

    for i in "$@"; do
    log "Appending $i"
    dd if="$i" of="$split_a" bs=32M oflag=append conv=notrunc status=progress
    dd if="$i" of="$split_a" bs=32M oflag=append conv=notrunc status=progress || cleanup 'dd exited with error: %s' "$?"
    if [ "$opt_delete" = 'true' ]; then
    rm -vf "$i"
    rm -vf "$i" || log 'failed to rm %s' "$i"
    fi
    done

    mv -vf "$split_a" "$target"
    exit 0
  2. crasm created this gist Sep 8, 2023.
    101 changes: 101 additions & 0 deletions gguf-merge.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,101 @@
    #!/bin/sh

    set -e

    log() {
    format="$1"; shift
    # shellcheck disable=SC2059
    >&2 printf "$format\n" "$@"
    }

    usage() {
    >&2 cat <<EOF
    usage: $(basename "$0") [-d] <model-prefix>
    options:
    -d (delete split files during merge, saves space)
    example:
    $ $(basename "$0") airoboros-l2-70b-2.1-creative.Q8_0.gguf-split-
    Merging:
    airoboros-l2-70b-2.1-creative.Q8_0.gguf-split-a
    airoboros-l2-70b-2.1-creative.Q8_0.gguf-split-b
    Into:
    airoboros-l2-70b-2.1-creative.Q8_0.gguf
    ...
    EOF
    exit 1
    }

    # This is called by an interrupt
    # shellcheck disable=SC2317
    cleanup() {
    log "Interrupted..."
    if [ -w "$split_a" ] && [ -n "$split_a_size" ]; then
    log 'Truncating "%s" to original size: %s bytes\n' "$split_a" "$split_a_size"
    truncate -c -s "$split_a_size" "$split_a"
    fi
    exit 1
    }

    opt_delete=
    while getopts 'd' opt; do
    case $opt in
    'd')
    opt_delete='true'
    shift
    ;;
    '?')
    log 'Invalid option: %s' "-$OPTARG"
    usage
    esac
    done

    if [ "$#" -ne 1 ]; then
    usage
    fi

    model="$1"

    # Load file glob into arg array
    set -- "${model}"*

    # Check if the glob failed to expand
    if [ "$1" = "${model}*" ]; then
    log 'No files found.'
    exit 1
    fi

    split_a="$1"
    split_a_size="$(stat -c '%s' "$split_a")"

    target="$(echo "$split_a" | sed 's/-split-a$//')"

    log 'Merging:'
    log '\t%s' "$@"
    log 'Into:\n\t%s\n' "$target"

    >&2 printf 'Continue? [Y/n] '
    read -r response
    case "$response" in
    [Yy]|"") ;;
    *)
    log 'Exiting...'
    exit 0
    ;;
    esac

    # Enable cleanup hook now, since we will begin operating on the files
    trap cleanup INT

    # Remove $1 (...-split-a) from arg array, which is the target for the appends
    shift

    for i in "$@"; do
    log "Appending $i"
    dd if="$i" of="$split_a" bs=32M oflag=append conv=notrunc status=progress
    if [ "$opt_delete" = 'true' ]; then
    rm -vf "$i"
    fi
    done

    mv -vf "$split_a" "$target"
    exit 0