Skip to content

Instantly share code, notes, and snippets.

@padeoe
Last active July 6, 2026 08:36
Show Gist options
  • Select an option

  • Save padeoe/697678ab8e528b85a2a7bddafea1fa4f to your computer and use it in GitHub Desktop.

Select an option

Save padeoe/697678ab8e528b85a2a7bddafea1fa4f to your computer and use it in GitHub Desktop.
CLI-Tool for download Huggingface models and datasets with aria2/wget: hfd

🤗Huggingface Model Downloader

Note

(2026-06-18) Add 📊Download Progress, 🔁integrity-aware resume (re-fetch missing or changed files), and fast, resumable listing for 📚repos with massive file counts.
(2025-01-08) Add feature for 🏷️Tag(Revision) Selection, contributed by @Bamboo-D.
(2024-12-17) Add feature for ⚡Quick Startup and ⏭️Fast Resume, enabling skipping of downloaded files, while removing the git clone dependency to accelerate file list retrieval.

Considering the lack of multi-threaded download support in the official huggingface-cli, and the inadequate error handling in hf_transfer, This command-line tool leverages curl and aria2c for fast and robust downloading of models and datasets.

Features

  • ⏯️ Resume & self-heal: Re-run or press Ctrl+C anytime; it skips files already complete and re-fetches only what's missing or the wrong size.
  • 🚀 Multi-threaded Download: Utilize multiple threads to speed up the download process.
  • 📊 Download Progress: A single live status line reports the total repo size up front, then files downloaded / total, data volume, speed, and ETA.
  • 📚 Large Repo Support: Reliably downloads repositories with very large numbers of files (e.g. big datasets), where the basic file list would otherwise be truncated.
  • 🚫 File Exclusion: Use --exclude or --include to skip or specify files, save time for models with duplicate formats (e.g., *.bin or *.safetensors).
  • 🔐 Auth Support: For gated models that require Huggingface login, use --hf_username and --hf_token to authenticate.
  • 🪞 Mirror Site Support: Set up with HF_ENDPOINT environment variable.
  • 🌍 Proxy Support: Set up with https_proxy environment variable.
  • 📦 Simple: Minimal dependencies, requires only curl and wget, while aria2 and jq are optional for better performance.
  • 🏷️ Tag Selection: Support downloading specific model/dataset revision using --revision.

Usage

First, Download hfd.sh or clone this repo, and then grant execution permission to the script.

chmod a+x hfd.sh

you can create an alias for convenience

alias hfd="$PWD/hfd.sh"

Usage Instructions

$ ./hfd.sh --help
Usage:
  hfd <REPO_ID> [--include include_pattern1 include_pattern2 ...] [--exclude exclude_pattern1 exclude_pattern2 ...] [--hf_username username] [--hf_token token] [--tool aria2c|wget] [-x threads] [-j jobs] [--dataset] [--local-dir path] [--revision rev]

Description:
  Downloads a model or dataset from Hugging Face using the provided repo ID.

Arguments:
  REPO_ID         The Hugging Face repo ID (Required)
                  Format: 'org_name/repo_name' or legacy format (e.g., gpt2)
Options:
  include/exclude_pattern The patterns to match against file path, supports wildcard characters.
                  e.g., '--exclude *.safetensor *.md', '--include vae/*'.
  --include       (Optional) Patterns to include files for downloading (supports multiple patterns).
  --exclude       (Optional) Patterns to exclude files from downloading (supports multiple patterns).
  --hf_username   (Optional) Hugging Face username for authentication (not email).
  --hf_token      (Optional) Hugging Face token for authentication.
  --tool          (Optional) Download tool to use: aria2c (default) or wget.
  -x              (Optional) Number of download threads for aria2c (default: 4).
  -j              (Optional) Number of concurrent downloads for aria2c (default: 5).
  --dataset       (Optional) Flag to indicate downloading a dataset.
  --local-dir     (Optional) Directory path to store the downloaded data.
                             Defaults to the current directory with a subdirectory named 'repo_name'
                             if REPO_ID is composed of 'org_name/repo_name'.
  --revision      (Optional) Model/Dataset revision to download (default: main).

Example:
  hfd gpt2
  hfd bigscience/bloom-560m --exclude *.bin *.msgpack onnx/*
  hfd meta-llama/Llama-2-7b --hf_username myuser --hf_token mytoken -x 4
  hfd lavita/medical-qa-shared-task-v1-toy --dataset
  hfd bartowski/Phi-3.5-mini-instruct-exl2 --revision 5_0

Download a model

hfd bigscience/bloom-560m

Download a model need login

Get huggingface token from https://huggingface.co/settings/tokens, then

hfd meta-llama/Llama-2-7b --hf_username YOUR_HF_USERNAME_NOT_EMAIL --hf_token YOUR_HF_TOKEN

Download a model and exclude certain files (e.g., .safetensors)

hfd bigscience/bloom-560m --exclude *.bin *.msgpack onnx/*

You can also exclude multiple pattern like that

hfd bigscience/bloom-560m --exclude *.bin --exclude *.msgpack --exclude onnx/*

Download specific files using include patterns

hfd Qwen/Qwen2.5-Coder-32B-Instruct-GGUF --include *q2_k*.gguf

Download a dataset

hfd lavita/medical-qa-shared-task-v1-toy --dataset

Download a specific revision of a model

hfd bartowski/Phi-3.5-mini-instruct-exl2 --revision 5_0

Download Progress

During download a single status line reports overall progress, refreshed in place:

bloom-560m (main)
Repository size: 5.63GB
Listing files...
Downloading 26 files to bloom-560m  ·  Ctrl+C to stop, re-run to resume
[ 31%] 8/26 files |   1.75GB/   5.63GB |  118.40MB/s | ETA 00:32
Done. 26 files, 5.63GB in bloom-560m

It shows percent complete, files downloaded / total, data volume, current speed, and ETA.

Multi-threading and Parallel Downloads

The script supports two types of parallelism when using aria2c:

  • Threads per File (-x): Controls connections per file, usage: hfd gpt2 -x 8, recommended: 4-8, default: 4 threads.

  • Concurrent Files (-j): Controls simultaneous file downloads, usage: hfd gpt2 -j 3, recommended: 3-8, default: 5 files.

Combined usage:

hfd gpt2 -x 8 -j 3  # 8 threads per file, 3 files at once
#!/usr/bin/env bash
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; DIM='\033[2m'; BOLD='\033[1m'; NC='\033[0m' # No Color
trap 'printf "\n%bInterrupted. Re-run to resume.%b\n" "$YELLOW" "$NC"; exit 130' INT
# Format a byte count as a human-readable string (decimal units, matching the HF UI).
human() {
awk -v b="${1:-0}" 'BEGIN{u="B KB MB GB TB PB";n=split(u,a," ");i=1;
while(b>=1000&&i<n){b/=1000;i++} printf (i==1?"%d%s":"%.2f%s"),b,a[i]}'
}
display_help() {
cat << EOF
Usage:
hfd <REPO_ID> [--include include_pattern1 include_pattern2 ...] [--exclude exclude_pattern1 exclude_pattern2 ...] [--hf_username username] [--hf_token token] [--tool aria2c|wget] [-x threads] [-j jobs] [--dataset] [--local-dir path] [--revision rev]
Description:
Downloads a model or dataset from Hugging Face using the provided repo ID.
Arguments:
REPO_ID The Hugging Face repo ID (Required)
Format: 'org_name/repo_name' or legacy format (e.g., gpt2)
Options:
include/exclude_pattern The patterns to match against file path, supports wildcard characters.
e.g., '--exclude *.safetensor *.md', '--include vae/*'.
--include (Optional) Patterns to include files for downloading (supports multiple patterns).
--exclude (Optional) Patterns to exclude files from downloading (supports multiple patterns).
--hf_username (Optional) Hugging Face username for authentication (not email).
--hf_token (Optional) Hugging Face token for authentication.
--tool (Optional) Download tool to use: aria2c (default) or wget.
-x (Optional) Number of download threads for aria2c (default: 4).
-j (Optional) Number of concurrent downloads for aria2c (default: 5).
--dataset (Optional) Flag to indicate downloading a dataset.
--local-dir (Optional) Directory path to store the downloaded data.
Defaults to the current directory with a subdirectory named 'repo_name'
if REPO_ID is composed of 'org_name/repo_name'.
--revision (Optional) Model/Dataset revision to download (default: main).
Example:
hfd gpt2
hfd bigscience/bloom-560m --exclude *.safetensors
hfd meta-llama/Llama-2-7b --hf_username myuser --hf_token mytoken -x 4
hfd lavita/medical-qa-shared-task-v1-toy --dataset
hfd bartowski/Phi-3.5-mini-instruct-exl2 --revision 5_0
EOF
exit 1
}
[[ -z "$1" || "$1" =~ ^-h || "$1" =~ ^--help ]] && display_help
REPO_ID=$1
shift
# Default values
TOOL="aria2c"
THREADS=4
CONCURRENT=5
HF_ENDPOINT=${HF_ENDPOINT:-"https://huggingface.co"}
INCLUDE_PATTERNS=()
EXCLUDE_PATTERNS=()
REVISION="main"
validate_number() {
[[ "$2" =~ ^[1-9][0-9]*$ && "$2" -le "$3" ]] || { printf "%b[Error] %s must be 1-%s%b\n" "$RED" "$1" "$3" "$NC"; exit 1; }
}
# Argument parsing
while [[ $# -gt 0 ]]; do
case $1 in
--include) shift; while [[ $# -gt 0 && ! ($1 =~ ^--) && ! ($1 =~ ^-[^-]) ]]; do INCLUDE_PATTERNS+=("$1"); shift; done ;;
--exclude) shift; while [[ $# -gt 0 && ! ($1 =~ ^--) && ! ($1 =~ ^-[^-]) ]]; do EXCLUDE_PATTERNS+=("$1"); shift; done ;;
--hf_username) HF_USERNAME="$2"; shift 2 ;;
--hf_token) HF_TOKEN="$2"; shift 2 ;;
--tool)
[[ "$2" == aria2c || "$2" == wget ]] || { printf "%b[Error] Invalid tool. Use 'aria2c' or 'wget'.%b\n" "$RED" "$NC"; exit 1; }
TOOL="$2"; shift 2 ;;
-x) validate_number "threads (-x)" "$2" 10; THREADS="$2"; shift 2 ;;
-j) validate_number "concurrent downloads (-j)" "$2" 10; CONCURRENT="$2"; shift 2 ;;
--dataset) DATASET=1; shift ;;
--local-dir) LOCAL_DIR="$2"; shift 2 ;;
--revision) REVISION="$2"; shift 2 ;;
*) display_help ;;
esac
done
# A fingerprint of the options that affect the file list; a change forces regeneration.
generate_command_string() {
printf 'REPO_ID=%s TOOL=%s INCLUDE=%s EXCLUDE=%s DATASET=%s HF_USERNAME=%s HF_TOKEN=%s HF_ENDPOINT=%s REVISION=%s' \
"$REPO_ID" "$TOOL" "${INCLUDE_PATTERNS[*]}" "${EXCLUDE_PATTERNS[*]}" "${DATASET:-0}" \
"${HF_USERNAME:-}" "${HF_TOKEN:-}" "${HF_ENDPOINT:-}" "$REVISION"
}
check_command() {
if ! command -v "$1" &>/dev/null; then
printf "%b%s is not installed. Please install it first.%b\n" "$RED" "$1" "$NC"
exit 1
fi
}
check_command curl; check_command "$TOOL"
LOCAL_DIR="${LOCAL_DIR:-${REPO_ID#*/}}"
mkdir -p "$LOCAL_DIR/.hfd"
REPO_API_PATH="models/$REPO_ID"; DOWNLOAD_API_PATH="$REPO_ID"
[[ "$DATASET" == 1 ]] && { REPO_API_PATH="datasets/$REPO_ID"; DOWNLOAD_API_PATH=$REPO_API_PATH; }
# wget --cut-dirs strips "<download_api_path>/resolve/<revision>/"; a fixed value wrongly
# assumes the org/name form and eats a directory level for legacy (single-name) repo ids.
CUT_DIRS=$(( $(printf '%s' "$DOWNLOAD_API_PATH" | tr -cd '/' | wc -c) + 3 ))
# Metadata API URL (used for the gated/auth check); append revision when not main.
METADATA_API_PATH="$REPO_API_PATH"
[[ "$REVISION" != "main" ]] && METADATA_API_PATH="$METADATA_API_PATH/revision/$REVISION"
API_URL="$HF_ENDPOINT/api/$METADATA_API_PATH?blobs=true"
METADATA_FILE="$LOCAL_DIR/.hfd/repo_metadata.json"
fetch_and_save_metadata() {
status_code=$(curl -L -s -w "%{http_code}" -o "$METADATA_FILE" ${HF_TOKEN:+-H "Authorization: Bearer $HF_TOKEN"} "$API_URL")
RESPONSE=$(cat "$METADATA_FILE")
if [ "$status_code" -eq 200 ]; then
printf "%s\n" "$RESPONSE"
else
printf "%b[Error] Failed to fetch metadata from %s. HTTP status code: %s.%b\n%s\n" "$RED" "$API_URL" "$status_code" "$NC" "$RESPONSE" >&2
rm -f "$METADATA_FILE"
exit 1
fi
}
# Exit early if the repo is gated/private but no credentials were supplied.
check_authentication() {
local gated
if command -v jq &>/dev/null; then
gated=$(printf '%s' "$1" | jq -r '.gated // false')
else
printf '%s' "$1" | grep -q '"gated":[^f]' && gated=true || gated=false
fi
if [[ "$gated" != "false" && ( -z "$HF_TOKEN" || -z "$HF_USERNAME" ) ]]; then
printf "%bThe repository requires authentication, but --hf_username and --hf_token is not passed. Please get token from https://huggingface.co/settings/tokens.\nExiting.\n%b" "$RED" "$NC"
exit 1
fi
}
printf "%b%s%b (%s)\n" "$BOLD" "$REPO_ID" "$NC" "$REVISION"
if [[ ! -f "$METADATA_FILE" ]]; then
printf "%bFetching metadata...%b\n" "$DIM" "$NC"
RESPONSE=$(fetch_and_save_metadata) || exit 1
else
RESPONSE=$(cat "$METADATA_FILE")
fi
check_authentication "$RESPONSE"
# Total bytes of the revision (cheap, branch-specific); empty if the endpoint lacks this API.
fetch_treesize() {
local json
json=$(curl -sSL ${HF_TOKEN:+-H "Authorization: Bearer $HF_TOKEN"} "$HF_ENDPOINT/api/$REPO_API_PATH/treesize/$REVISION") || return
if command -v jq &>/dev/null; then
printf '%s' "$json" | jq -r '.size // empty' 2>/dev/null
else
printf '%s' "$json" | grep -o '"size":[0-9]*' | head -1 | grep -o '[0-9]*'
fi
}
# Reuse the cached list only if the command is unchanged AND the manifest is intact (its line
# count equals repo_info's total). An interrupted/failed walk leaves no repo_info, so it re-lists.
should_regenerate_filelist() {
local cmd="$LOCAL_DIR/.hfd/last_download_command" mf="$LOCAL_DIR/.hfd/manifest" info="$LOCAL_DIR/.hfd/repo_info"
[[ -f "$mf" && -f "$info" && "$(generate_command_string)" == "$(cat "$cmd" 2>/dev/null)" \
&& "$(wc -l < "$mf")" == "$(cut -d' ' -f1 "$info" 2>/dev/null)" ]] && return 1
return 0
}
fileslist_file=".hfd/${TOOL}_urls.txt"
# Convert a list of wildcard patterns into a single alternation regex.
patterns_to_regex() {
(($#)) || return 0
printf '%s\n' "$@" | sed 's/\./\\./g; s/\*/.*/g' | paste -sd '|' -
}
# Emit "size<TAB>path" for every file in a tree page (jq, or a grep/awk fallback).
emit_page_files() {
if command -v jq &>/dev/null; then
jq -r '.[] | select(.type=="file") | "\(.size)\t\(.path)"' "$1"
else
# Strip the nested lfs{} object (it has its own "size") so type/size/path align per entry.
sed 's/"lfs":{[^}]*}//g' "$1" \
| grep -oE '"type":"[^"]*"|"size":[0-9]+|"path":"[^"]*"' \
| sed 's/"type":"//; s/"size"://; s/"path":"//; s/"$//' \
| awk 'NR%3==1{t=$0} NR%3==2{s=$0} NR%3==0{if(t=="file")print s"\t"$0}'
fi
}
# Emit "size<TAB>path" for every file from the cached metadata siblings[] (needs jq).
emit_siblings() {
jq -r '(.siblings // [])[] | "\(.size // 0)\t\(.rfilename)"' "$METADATA_FILE"
}
# True when siblings[] is the complete list: its sizes sum to treesize (so it wasn't truncated, as
# it is for very large repos). Lets us skip the slow tree walk for typical repos via one API call.
siblings_complete() {
command -v jq &>/dev/null && [[ "$REPO_SIZE" =~ ^[0-9]+$ ]] || return 1
local n s
read -r n s < <(jq -r '(.siblings // []) as $s | "\($s|length) \([$s[].size // 0]|add // 0)"' "$METADATA_FILE" 2>/dev/null)
(( ${n:-0} > 0 )) && [[ "${s:-0}" == "$REPO_SIZE" ]]
}
# Keep only "size<TAB>path" stdin lines matching include/exclude (the *_REGEX globals).
filter_size_path() {
local size path
while IFS=$'\t' read -r size path; do
[[ -z "$path" ]] && continue
[[ -n "$INCLUDE_REGEX" && ! "$path" =~ $INCLUDE_REGEX ]] && continue
[[ -n "$EXCLUDE_REGEX" && "$path" =~ $EXCLUDE_REGEX ]] && continue
printf '%s\t%s\n' "${size:-0}" "$path"
done
}
# Resumably walk the recursive tree into .hfd/manifest.partial (filtered size<TAB>path). After each
# page, checkpoint .hfd/list_state (fingerprint / entries scanned / next cursor) so an interrupted or
# failed walk continues from there instead of restarting. Progress (entries scanned) goes to stderr.
walk_tree() {
local state="$LOCAL_DIR/.hfd/list_state" partial="$LOCAL_DIR/.hfd/manifest.partial"
local page="$LOCAL_DIR/.hfd/tree_page.json" fp url scanned=0 headers n saved_fp=""
fp=$(generate_command_string)
[[ -f "$state" && -f "$partial" ]] && { read -r saved_fp; read -r scanned; read -r url; } < "$state"
if [[ "$saved_fp" != "$fp" ]]; then # no checkpoint, or it belongs to a different command
url="$HF_ENDPOINT/api/$REPO_API_PATH/tree/$REVISION?recursive=true&expand=false"
scanned=0; : > "$partial"
elif [[ -s "$partial" && -n "$(tail -c1 "$partial")" ]]; then
sed -i '$d' "$partial" # drop a torn final line from a kill mid-append (the page re-fetches)
fi
while [[ -n "$url" ]]; do
headers=$(curl -sSL ${HF_TOKEN:+-H "Authorization: Bearer $HF_TOKEN"} -D - -o "$page" "$url") || return 1
if command -v jq &>/dev/null; then n=$(jq 'length' "$page" 2>/dev/null); else n=$(grep -o '"type":"' "$page" | wc -l); fi
emit_page_files "$page" | filter_size_path >> "$partial"
scanned=$(( scanned + ${n:-0} ))
printf '\r\033[K%bListing files... %d scanned%b' "$DIM" "$scanned" "$NC" >&2
url=$(printf '%s' "$headers" | tr -d '\r' | grep -i '^link:' \
| grep -o '<[^>]*>;[[:space:]]*rel="next"' | sed -n 's/^<\([^>]*\)>.*/\1/p')
printf '%s\n%s\n%s\n' "$fp" "$scanned" "$url" > "$state" # checkpoint after the page is in
done
return 0
}
# Dedup .hfd/manifest.partial by path (a resumed walk may re-list its boundary page) into the final
# manifest, and write "<count> <bytes>" totals to filelist_stats.
finalize_filelist() {
local mf="$LOCAL_DIR/.hfd/manifest"
: > "$mf"
awk -F'\t' -v mf="$mf" '!seen[$2]++ { print >> mf; n++; s+=$1 } END { print (n+0)" "(s+0) }' \
"$LOCAL_DIR/.hfd/manifest.partial" > "$LOCAL_DIR/.hfd/filelist_stats"
}
# Build tool input from the manifest; set NEED_COUNT (files still to fetch). One find pass diffs
# the tree, keeping files missing or the wrong size (.aria2 sidecar = in-progress, kept): cheap
# for huge repos, correct after a manual delete. Run from the local dir (manifest paths relative).
build_download_list() {
local needed=.hfd/needed size path dir cur
if [[ ! -s .hfd/manifest ]]; then NEED_COUNT=0; : > "$fileslist_file"; return; fi
awk -F'\t' '
FNR==NR { want[$2]=$1; ord[++n]=$2; next }
{ p=$2; sub(/^\.\//,"",p);
if (p ~ /\.aria2$/) { sub(/\.aria2$/,"",p); part[p]=1 } else have[p]=$1 }
END { for (i=1;i<=n;i++) { q=ord[i];
if ((q in have) && have[q]==want[q] && !(q in part)) continue;
print want[q] "\t" q } }
' .hfd/manifest <(find . -type f ! -path './.hfd/*' -printf '%s\t%p\n' 2>/dev/null) > "$needed"
NEED_COUNT=$(wc -l < "$needed")
# Per needed file: drop a wrong-size copy -c/--continue can't fix in place (aria2c with no
# .aria2 control file, or a wget file larger than expected) for a fresh refetch; emit the record.
while IFS=$'\t' read -r size path; do
[[ -z "$path" ]] && continue
if [[ "$TOOL" == "aria2c" ]]; then
[[ -e "$path" && ! -e "$path.aria2" ]] && rm -f "$path"
dir="${path%/*}"; [[ "$dir" == "$path" ]] && dir=""
printf '%s/%s/resolve/%s/%s\n dir=%s\n out=%s\n' "$HF_ENDPOINT" "$DOWNLOAD_API_PATH" "$REVISION" "$path" "$dir" "${path##*/}"
[[ -n "$HF_TOKEN" ]] && printf ' header=Authorization: Bearer %s\n' "$HF_TOKEN"
printf '\n'
else
cur=$(stat -c%s "$path" 2>/dev/null || echo 0); (( cur > size )) && rm -f "$path"
printf '%s/%s/resolve/%s/%s\n' "$HF_ENDPOINT" "$DOWNLOAD_API_PATH" "$REVISION" "$path"
fi
done < "$needed" > "$fileslist_file"
rm -f "$needed"
}
if should_regenerate_filelist; then
command -v jq &>/dev/null || printf "%b[Warning] jq not installed, using grep/awk for json parsing (slower). Consider installing jq.%b\n" "$YELLOW" "$NC"
# Total size up front (before the long walk); label the call so its few-second wait isn't silent.
printf "%bFetching repository info...%b" "$DIM" "$NC"
REPO_SIZE=$(fetch_treesize); printf '\r\033[K'
[[ "$REPO_SIZE" =~ ^[0-9]+$ ]] && printf "%bRepository size: %s%b\n" "$DIM" "$(human "$REPO_SIZE")" "$NC"
INCLUDE_REGEX=$(patterns_to_regex "${INCLUDE_PATTERNS[@]}")
EXCLUDE_REGEX=$(patterns_to_regex "${EXCLUDE_PATTERNS[@]}")
printf "%bListing files...%b" "$DIM" "$NC"
# Fast path: typical repos return their whole file list in the metadata; only big repos
# (truncated siblings) need the paginated, resumable tree walk.
if siblings_complete; then
rm -f "$LOCAL_DIR/.hfd/list_state"
emit_siblings | filter_size_path > "$LOCAL_DIR/.hfd/manifest.partial"
gen_status=${PIPESTATUS[0]}
else
walk_tree; gen_status=$?
fi
# A failed walk keeps its checkpoint (list_state + manifest.partial), so a re-run resumes.
(( gen_status == 0 )) || { printf "\n%b[Error] Failed to list repository files. Re-run to resume.%b\n" "$RED" "$NC" >&2; exit 1; }
finalize_filelist
read -r TOTAL_FILES SUM_SIZE < "$LOCAL_DIR/.hfd/filelist_stats"
printf '\r\033[K%bListed %d files (%s)%b\n' "$DIM" "$TOTAL_FILES" "$(human "$SUM_SIZE")" "$NC"
# Whole-revision total from treesize; the summed filtered size when include/exclude narrows it.
TOTAL_SIZE=$REPO_SIZE
[[ -n "$INCLUDE_REGEX$EXCLUDE_REGEX" || ! "$REPO_SIZE" =~ ^[0-9]+$ ]] && TOTAL_SIZE=$SUM_SIZE
printf '%s %s\n' "$TOTAL_FILES" "$TOTAL_SIZE" > "$LOCAL_DIR/.hfd/repo_info"
# Fingerprint written last: marks the list complete (an interrupted walk has none, so it re-lists).
generate_command_string > "$LOCAL_DIR/.hfd/last_download_command"
rm -f "$LOCAL_DIR/.hfd/manifest.partial" "$LOCAL_DIR/.hfd/list_state" "$LOCAL_DIR/.hfd/tree_page.json"
fi
cd "$LOCAL_DIR" || exit 1
# Render one in-place status line; speed = byte delta since last call (PREV_B/PREV_T).
# Fields are fixed-width so columns don't jitter as values grow a digit; ETA is last.
PREV_B=0; PREV_T=0
render_progress() {
local now=$1 dfiles=$2 dt sp pct eta e
dt=$(( SECONDS - PREV_T )); ((dt<1)) && dt=1
sp=$(( (now - PREV_B) / dt )); ((sp<0)) && sp=0; PREV_B=$now; PREV_T=$SECONDS
pct=0; ((TOTAL_SIZE>0)) && pct=$(( now * 100 / TOTAL_SIZE )); ((pct>100)) && pct=100
# ETA only once speed is meaningful; clamp absurd early estimates to keep it tidy.
eta="--:--"; ((sp>0 && TOTAL_SIZE>now)) && { e=$(( (TOTAL_SIZE-now)/sp )); ((e<360000)) && eta=$(printf '%02d:%02d' $((e/60)) $((e%60))); }
printf '\r\033[K%b[%3d%%]%b %*d/%d files | %9s/%9s | %9s/s | ETA %s' \
"$GREEN" "$pct" "$NC" "${#TOTAL_FILES}" "$dfiles" "$TOTAL_FILES" \
"$(human "$now")" "$(human "$TOTAL_SIZE")" "$(human "$sp")" "$eta"
}
# Progress without scanning finished files: manifest totals + a stat of only in-flight files.
monitor_progress() {
local interval=$1 base=$1 stop_hint="Stopping download, please wait..."; PREV_T=$SECONDS
# The main INT trap is deferred until the foreground download returns, so acknowledge
# Ctrl+C here (fires at once in the subshell) and note the force-stop that already works.
[[ "$TOOL" == "aria2c" ]] && stop_hint="Stopping download, please wait... (press Ctrl+C again to force stop)"
trap 'printf "\n%b%s%b\n" "$YELLOW" "$stop_hint" "$NC"; exit 0' INT
if [[ "$TOOL" == "wget" ]]; then
# wget downloads in manifest order, so a forward cursor needs to stat only the
# current file; everything before it is done and counted by its known size.
local -a MS MP; local s p
while IFS=$'\t' read -r s p; do MS+=("$s"); MP+=("$p"); done < .hfd/manifest
local idx=0 done_b=0 cur
while :; do
sleep "$interval"
while (( idx < ${#MP[@]} )); do
cur=$(stat -c%s "${MP[idx]}" 2>/dev/null) || break
(( cur >= MS[idx] )) || break
done_b=$(( done_b + MS[idx] )); idx=$((idx+1))
done
cur=0; (( idx < ${#MP[@]} )) && cur=$(stat -c%s "${MP[idx]}" 2>/dev/null || echo 0)
render_progress $(( done_b + cur )) "$idx"
done
else
# Parallel downloads finish out of order, so a cursor would miss files completing between
# ticks. Each tick sums block usage (sparse-aware) of the manifest's files only — ignoring
# stale files left from an earlier version of the repo — minus in-progress (.aria2) ones.
local now files t0 walk
while :; do
sleep "$interval"
t0=$SECONDS
read -r now files < <(awk -F'\t' '
FNR==NR { want[$2]=1; next }
{ p=$2; sub(/^\.\//,"",p)
if (p ~ /\.aria2$/) { sub(/\.aria2$/,"",p); if (p in want) a++; next }
if (p in want) { b+=$1; d++ } }
END { print b*512, d-a }
' .hfd/manifest <(find . -type f ! -path './.hfd/*' -printf '%b\t%p\n' 2>/dev/null))
render_progress "$now" "$files"
# Self-throttle: if the walk took longer than the base interval, sleep that long
# next time so scanning stays under ~half the wall-clock at any repo size.
walk=$(( SECONDS - t0 )); interval=$base; (( walk > base )) && interval=$walk
done
fi
}
# Totals were persisted at file-list generation; reload for resumed runs.
[[ -f .hfd/repo_info ]] && read -r TOTAL_FILES TOTAL_SIZE < .hfd/repo_info
TOTAL_FILES=${TOTAL_FILES:-0}; TOTAL_SIZE=${TOTAL_SIZE:-0}
FILE_NOUN="files"; ((TOTAL_FILES==1)) && FILE_NOUN="file"
# Diff the local tree against the manifest to find what's missing, then short-circuit if done.
((TOTAL_FILES>50000)) && printf "%bChecking local files...%b\n" "$DIM" "$NC"
build_download_list
if (( NEED_COUNT == 0 )); then
printf "%bUp to date. %s %s in %s%b\n" "$GREEN" "$TOTAL_FILES" "$FILE_NOUN" "$LOCAL_DIR" "$NC"
exit 0
fi
# "Resuming" if any data is already on disk (completed files or a partial), else a fresh start.
verb="Downloading"; [[ -n "$(find . -type f ! -path './.hfd/*' -print -quit 2>/dev/null)" ]] && verb="Resuming"
printf "%s %s %s to %s · Ctrl+C to stop, re-run to resume\n" "$verb" "$TOTAL_FILES" "$FILE_NOUN" "$LOCAL_DIR"
# Silence native per-file output (logged to .hfd/download.log) so the monitor owns one
# clean line. Refresh every 1s, backing off for huge repos where the walk gets expensive.
interval=1; ((TOTAL_FILES>50000)) && interval=5
monitor_progress "$interval" &
MON_PID=$!
trap 'kill "$MON_PID" 2>/dev/null' EXIT
if [[ "$TOOL" == "aria2c" ]]; then
aria2c --quiet=true --log=.hfd/download.log --log-level=error --file-allocation=none \
-x "$THREADS" -j "$CONCURRENT" -s "$THREADS" -k 1M -c -i "$fileslist_file" >/dev/null
status=$?
else
wget -x -nH --cut-dirs="$CUT_DIRS" ${HF_TOKEN:+--header="Authorization: Bearer $HF_TOKEN"} \
--input-file="$fileslist_file" --continue -nv -o .hfd/download.log
status=$?
fi
# Clear the live progress line in place; the final status line takes its spot (no blank line).
kill "$MON_PID" 2>/dev/null; wait "$MON_PID" 2>/dev/null; printf '\r\033[K'
if [[ $status -eq 0 ]]; then
printf "%bDone. %s %s, %s in %s%b\n" "$GREEN" "$TOTAL_FILES" "$FILE_NOUN" "$(human "$TOTAL_SIZE")" "$LOCAL_DIR" "$NC"
else
printf "%bDownload incomplete. Re-run to resume. Log: %s%b\n" "$RED" "$PWD/.hfd/download.log" "$NC"
exit 1
fi
@falcon-xu

falcon-xu commented May 21, 2025

Copy link
Copy Markdown

@padeoe 您好,目前调用脚本无法下载模型,目标路径下只有一个.hfd文件夹,无模型文件,运行信息如下:

$ ./hfd.sh microsoft/swin-base-patch4-window7-224-in22k  --local-dir ./swin-base-patch4-window7-224-in22k

Fetching repo metadata...                                                                                                                                                  
jq: error while loading shared libraries: libonig.so.5: cannot open shared object file: No such file or directory                                                          
Generating file list...                                                                                                                                                    
jq: error while loading shared libraries: libonig.so.5: cannot open shared object file: No such file or directory                                                          
Starting download with aria2c to ./swin-base-patch4-window7-224-in22k...                                                                                                   No files to download.                                                                                                                                                      
Download completed successfully. Repo directory: /data1/xuguanyu/code/checkpoint/swin-base-patch4-window7-224-in22k

已尝试如下方法,均无效:

  • 更换模型
  • 换用备用节点
  • 删除.hfd文件夹
  • 换用wget下载

请问应该如何处理?谢谢!

@falcon-xu

Copy link
Copy Markdown

@padeoe 您好,目前调用脚本无法下载模型,目标路径下只有一个.hfd文件夹,无模型文件,运行信息如下:

$ ./hfd.sh microsoft/swin-base-patch4-window7-224-in22k  --local-dir ./swin-base-patch4-window7-224-in22k

Fetching repo metadata...                                                                                                                                                  
jq: error while loading shared libraries: libonig.so.5: cannot open shared object file: No such file or directory                                                          
Generating file list...                                                                                                                                                    
jq: error while loading shared libraries: libonig.so.5: cannot open shared object file: No such file or directory                                                          
Starting download with aria2c to ./swin-base-patch4-window7-224-in22k...                                                                                                   No files to download.                                                                                                                                                      
Download completed successfully. Repo directory: /data1/xuguanyu/code/checkpoint/swin-base-patch4-window7-224-in22k

已尝试如下方法,均无效:

  • 更换模型
  • 换用备用节点
  • 删除.hfd文件夹
  • 换用wget下载

请问应该如何处理?谢谢!

更新 jq 后解决

@Seas0

Seas0 commented Jun 19, 2025

Copy link
Copy Markdown

The generate_command_string function seems to incorrectly save the HF_ENDPOINT environment variable as another HF_TOKEN, as shown at https://gist.github.com/padeoe/697678ab8e528b85a2a7bddafea1fa4f#file-hfd-sh-L99

@padeoe

padeoe commented Jun 19, 2025

Copy link
Copy Markdown
Author

The generate_command_string function seems to incorrectly save the HF_ENDPOINT environment variable as another HF_TOKEN, as shown at https://gist.github.com/padeoe/697678ab8e528b85a2a7bddafea1fa4f#file-hfd-sh-L99

Thanks, fixed!

@zigerZZZ

Copy link
Copy Markdown
(deepseek) shiny@cadd-cdob01-computer1:~/deepseek_local$ hfd.sh deepseek-ai/DeepSeek-R1-Distill-Qwen-32B --local-dir ./ds-Qwen
Fetching repo metadata...
cat: ./ds-Qwen/.hfd/repo_metadata.json: 没有那个文件或目录
[Error] Failed to fetch metadata from https://hf-mirror.com/api/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B. HTTP status code: 000.

rm: 无法删除 './ds-Qwen/.hfd/repo_metadata.json': 没有那个文件或目录
(deepseek) shiny@cadd-cdob01-computer1:~/deepseek_local$ rm -rf ./ds-Qwen/.hfd/
(deepseek) shiny@cadd-cdob01-computer1:~/deepseek_local$ hfd.sh deepseek-ai/DeepSeek-R1-Distill-Qwen-32B --local-dir ./ds-Qwen
Fetching repo metadata...
cat: ./ds-Qwen/.hfd/repo_metadata.json: 没有那个文件或目录
[Error] Failed to fetch metadata from https://hf-mirror.com/api/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B. HTTP status code: 000.

rm: 无法删除 './ds-Qwen/.hfd/repo_metadata.json': 没有那个文件或目录

你好,之前这个问题我也遇到了,删除./ds-Qwen/.hfd/这个目录不起作用

@Harperrrr111

Copy link
Copy Markdown

errorCode=1 SSL/TLS handshake failure: self-signed certificate in certificate chain 请问怎么解决呢

@Seas0

Seas0 commented Aug 13, 2025

Copy link
Copy Markdown

errorCode=1 SSL/TLS handshake failure: self-signed certificate in certificate chain 请问怎么解决呢

检查你的系统证书,或者你的网络需要身份认证;或者给下载器加个忽略SSL证书检查参数。

@Harperrrr111

Copy link
Copy Markdown

errorCode=1 SSL/TLS handshake failure: self-signed certificate in certificate chain 请问怎么解决呢

检查你的系统证书,或者你的网络需要身份认证;或者给下载器加个忽略SSL证书检查参数。

谢谢!解决了~

@xiotong0112

Copy link
Copy Markdown

请问这是什么问题,有什么办法解决吗? [DL:19MiB][#90b682 7.5GiB/10GiB(74%)][#2f1d57 1.6GiB/22GiB(7%)] 03/24 00:08:38 [ERROR] CUID#13 - Download aborted. URI=xxx Exception: [AbstractCommand.cc:351] errorCode=22 URI=xxx -> [HttpSkipResponseCommand.cc:239] errorCode=22 The response status is not successful. status=429

访问频率过快,被限制了

请问这个能通过调什么命令参数来缓解吗?需要下载的文件比较多,现在用的都是默认参数

你好解决了吗,我遇到了同样的问题

@padeoe

padeoe commented Oct 18, 2025

Copy link
Copy Markdown
Author

@xiotong0112 近期429问题是因为hf上游对访问频率进行了更严格的限制,可以通过传递--hf_username--hf_token参数实现登录,可以提高访问频率额度

@xiotong0112

Copy link
Copy Markdown

@xiotong0112 近期429问题是因为hf上游对访问频率进行了更严格的限制,可以通过传递--hf_username--hf_token参数实现登录,可以提高访问频率额度

感谢回复。还想请教一下,仓库文件数量太多,repo返回的文件列表不全,这种情况下怎么能下载仓库中完整的文件啊

@padeoe

padeoe commented Oct 21, 2025 via email

Copy link
Copy Markdown
Author

@eternity123-null

eternity123-null commented Nov 3, 2025

Copy link
Copy Markdown

您好,我用hfd下载数据集,还有一些文件没下载下来,命令行却提示已经下载完成了,请问有什么解决方法吗?
发现是repo_metadata.json中就少了缺失的文件那部分,换个位置重新下载发现repo_metadata.json仍然是不完整的。Dataset是behavior-1k/2025-challenge-demos

@Leslie-Luo

Copy link
Copy Markdown

大佬 微信群二维码过期了,麻烦更新一下

@padeoe

padeoe commented Nov 26, 2025

Copy link
Copy Markdown
Author

@Leslie-Luo 已更新,感谢提醒

@Gengsheng-Li

Copy link
Copy Markdown

@Leslie-Luo 已更新,感谢提醒

大佬,请问二维码在哪里呀?

@padeoe

padeoe commented Dec 1, 2025

Copy link
Copy Markdown
Author

@Leslie-Luo 已更新,感谢提醒

大佬,请问二维码在哪里呀?

在 hf-mirror.com 网站首页底部

@Gengsheng-Li

Copy link
Copy Markdown

还想请教大佬一个问题:
我在使用 ./hfd.sh Alibaba-NLP/Tongyi-DeepResearch-30B-A3B --tool aria2c -x 10 --local-dir ./models/Tongyi-DeepResearch-30B-A3B的时候有几个模型的safetensor文件出现了以下报错,最后下载失败了(但是也有几个下载成功了)。后面再次使用相同的指令打算断点重下时还是出现了一样的错误,不知道这是怎么回事?翻了全网也没能找到解决办法,想求助下大佬。

[DL:318KiB][#902d79 668MiB/3.7GiB(17%)][#8aa93b 666MiB/3.7GiB(17%)][#2ae6fc 1.0GiB/3.7GiB(29%)][#aa131c 2.1GiB/3.7GiB(57%)][#162f45 2.4GiB/3.7GiB(66%)]                                                                                                  
12/01 00:51:15 [ERROR] CUID#147 - Download aborted. URI=https://hf-mirror.com/Alibaba-NLP/Tongyi-DeepResearch-30B-A3B/resolve/main/model-00007-of-00016.safetensors                                                                                     
Exception: [AbstractCommand.cc:351] errorCode=8 URI=https://cas-bridge.xethub.hf-mirror.com/xet-bridge-us/68c90a317d4233e576219173/f0d0c0d0c2329cad49af3662709be5646d23c0630360214a4490b67f01553ec7?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha25$=UNSIGNED-PAYLOAD&X-Amz-Credential=cas%2F20251201%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251201T055114Z&X-Amz-Expires=3600&X-Amz-Signature=98cafa0ad9bf003ab5ef096aaef618c6795554779d7491c222c73cd1f6eb8df4&X-Amz-SignedHeaders=host&X-Xet-Cas-Uid$62171e3b6a99db28e0b3159d&response-content-disposition=inline%3B+filename*%3DUTF-8%27%27model-00007-of-00016.safetensors%3B+filename%3D%22model-00007-of-00016.safetensors%22%3B&x-id=GetObject&Expires=1764571874&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGl$biI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTc2NDU3MTg3NH19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2FzLWJyaWRnZS54ZXRodWIuaGYuY28veGV0LWJyaWRnZS11cy82OGM5MGEzMTdkNDIzM2U1NzYyMTkxNzMvZjBkMGMwZDBjMjMyOWNhZDQ5YWYzNjYyNzA5YmU1NjQ2ZDIzYzA2MzAzNjAyMTRhNDQ5MGI2$2YwMTU1M2VjNyoifV19&Signature=JvGp1IQ9VFbOIjh%7EEljxKbpIj5jl8yWWAPr4o5%7EywsxBtas5L2EgZi6cNWMAP5g2GFCZs9wPcNByLq5Xp0VMoYd%7EOc7x21sfBVLqYQZ-NszYC9WunpMzFDqebFg-MRUWCNu-CP9-F6-jj6GKinm5J3rCB3CacNMinb1jL47jAs7f0i2cI8vwcK1zoC1MMn7zDoqAFJTpxljdQlCbJDk8$InlIlx8QavuLYi3Kf15VIMMEl576gfr%7Er1LusJwlGx4EIBx%7EbuKdCo52TrEjy9FX1jazFcBE76NB2SpfDzknD4olrbqOR-1CV41z-uO1DwbDNM1BEP%7EJaT8OUuyIiVEow__&Key-Pair-Id=K2L8F4GPSG1IFC                                                                                    
  -> [HttpResponse.cc:86] errorCode=8 Invalid range header. Request: 3041079195-3501195263/3999975416, Response: 0-3999975415/3999975416

@Gengsheng-Li

Copy link
Copy Markdown

@Leslie-Luo 已更新,感谢提醒

大佬,请问二维码在哪里呀?

在 hf-mirror.com 网站首页底部

谢谢佬,佬回得真快,感动~

@ranyev5

ranyev5 commented Dec 8, 2025

Copy link
Copy Markdown

大佬二维码过期了

@Littleor

Littleor commented Jan 4, 2026

Copy link
Copy Markdown

最近使用 hf-mirror 的过程中出现了 IP Limitation:

We had to rate limit your IP (162.159.*.*). To continue using our service, create a HF account or login to your existing account, and make sure you pass a HF_TOKEN if you're using the API.

需要配置 HF_TOKEN 以解决限流问题,然而 hfd.sh 每次都需要配置对应参数,直接写死在 env 在部分环境下不适合,因此更新了下脚本支持本地文件持久化 HF_TOKEN 和 HF_USERNAME:https://gist.github.com/Littleor/a159f06d5a5ba533b7c84a83ddd69dc0/revisions

用法:

$ ./hfd.sh login
Enter Hugging Face Username: ***
Enter Hugging Face Token: ***
Credentials saved to ~/.hfd_config

后续即可不带参数直接下载模型/数据集,减少输入复杂度。

@dichen-cd

Copy link
Copy Markdown

还想请教大佬一个问题: 我在使用 ./hfd.sh Alibaba-NLP/Tongyi-DeepResearch-30B-A3B --tool aria2c -x 10 --local-dir ./models/Tongyi-DeepResearch-30B-A3B的时候有几个模型的safetensor文件出现了以下报错,最后下载失败了(但是也有几个下载成功了)。后面再次使用相同的指令打算断点重下时还是出现了一样的错误,不知道这是怎么回事?翻了全网也没能找到解决办法,想求助下大佬。

[DL:318KiB][#902d79 668MiB/3.7GiB(17%)][#8aa93b 666MiB/3.7GiB(17%)][#2ae6fc 1.0GiB/3.7GiB(29%)][#aa131c 2.1GiB/3.7GiB(57%)][#162f45 2.4GiB/3.7GiB(66%)]                                                                                                  
12/01 00:51:15 [ERROR] CUID#147 - Download aborted. URI=https://hf-mirror.com/Alibaba-NLP/Tongyi-DeepResearch-30B-A3B/resolve/main/model-00007-of-00016.safetensors                                                                                     
Exception: [AbstractCommand.cc:351] errorCode=8 URI=https://cas-bridge.xethub.hf-mirror.com/xet-bridge-us/68c90a317d4233e576219173/f0d0c0d0c2329cad49af3662709be5646d23c0630360214a4490b67f01553ec7?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha25$=UNSIGNED-PAYLOAD&X-Amz-Credential=cas%2F20251201%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251201T055114Z&X-Amz-Expires=3600&X-Amz-Signature=98cafa0ad9bf003ab5ef096aaef618c6795554779d7491c222c73cd1f6eb8df4&X-Amz-SignedHeaders=host&X-Xet-Cas-Uid$62171e3b6a99db28e0b3159d&response-content-disposition=inline%3B+filename*%3DUTF-8%27%27model-00007-of-00016.safetensors%3B+filename%3D%22model-00007-of-00016.safetensors%22%3B&x-id=GetObject&Expires=1764571874&Policy=eyJTdGF0ZW1lbnQiOlt7IkNvbmRpdGl$biI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTc2NDU3MTg3NH19LCJSZXNvdXJjZSI6Imh0dHBzOi8vY2FzLWJyaWRnZS54ZXRodWIuaGYuY28veGV0LWJyaWRnZS11cy82OGM5MGEzMTdkNDIzM2U1NzYyMTkxNzMvZjBkMGMwZDBjMjMyOWNhZDQ5YWYzNjYyNzA5YmU1NjQ2ZDIzYzA2MzAzNjAyMTRhNDQ5MGI2$2YwMTU1M2VjNyoifV19&Signature=JvGp1IQ9VFbOIjh%7EEljxKbpIj5jl8yWWAPr4o5%7EywsxBtas5L2EgZi6cNWMAP5g2GFCZs9wPcNByLq5Xp0VMoYd%7EOc7x21sfBVLqYQZ-NszYC9WunpMzFDqebFg-MRUWCNu-CP9-F6-jj6GKinm5J3rCB3CacNMinb1jL47jAs7f0i2cI8vwcK1zoC1MMn7zDoqAFJTpxljdQlCbJDk8$InlIlx8QavuLYi3Kf15VIMMEl576gfr%7Er1LusJwlGx4EIBx%7EbuKdCo52TrEjy9FX1jazFcBE76NB2SpfDzknD4olrbqOR-1CV41z-uO1DwbDNM1BEP%7EJaT8OUuyIiVEow__&Key-Pair-Id=K2L8F4GPSG1IFC                                                                                    
  -> [HttpResponse.cc:86] errorCode=8 Invalid range header. Request: 3041079195-3501195263/3999975416, Response: 0-3999975415/3999975416

我也遇到了类似的情况,部分使用了xet的repo域名变成了xethub.hf.co 而不是 huggingface.co. 我猜测或许hf-mirror还没能cover到这种情况吧

@sonder718

Copy link
Copy Markdown

@xiotong0112 近期429问题是因为hf上游对访问频率进行了更严格的限制,可以通过传递--hf_username--hf_token参数实现登录,可以提高访问频率额度

感谢回复。还想请教一下,仓库文件数量太多,repo返回的文件列表不全,这种情况下怎么能下载仓库中完整的文件啊

你好解决了吗,我遇到了同样的问题

@luojiyin1987

Copy link
Copy Markdown

hfd.sh 的 87-88 行 原来是

cmd_string+=" HF_TOKEN=${HF_TOKEN:-}"                                                                                                                                                                                                                  
cmd_string+=" HF_TOKEN=${HF_ENDPOINT:-}"   

是不是应该改成

cmd_string+=" HF_TOKEN=${HF_TOKEN:-}"
cmd_string+=" HF_ENDPOINT=${HF_ENDPOINT:-}"

@padeoe

padeoe commented Jan 13, 2026

Copy link
Copy Markdown
Author

@luojiyin1987 感谢提醒, https://hf-mirror.com/hfd/hfd.sh 没更新到最新版本,确实存在typo,我今天更新

@padeoe

padeoe commented Mar 24, 2026

Copy link
Copy Markdown
Author

你这个相当于是一个代理吧, 并不是一个镜像, 对吧!

本仓库是huggingface的下载加速脚本

@c608345

c608345 commented Apr 16, 2026

Copy link
Copy Markdown

Feature Request: Could you support download repo branch? Thanks.

@padeoe

padeoe commented Apr 16, 2026

Copy link
Copy Markdown
Author

@c608345 Actually, the current --revision parameter already allows for branch selection. You can try it. I might add --branch as an alias for it.

@c608345

c608345 commented Apr 16, 2026

Copy link
Copy Markdown

I thought revision is used for commits, thanks.

@ligeng8848

Copy link
Copy Markdown

@padeoe 大佬 二维码过期了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment