Skip to content

Instantly share code, notes, and snippets.

@xbalaji
Last active May 31, 2026 00:37
Show Gist options
  • Select an option

  • Save xbalaji/28c2e8963c72070ce431306e0616fdb2 to your computer and use it in GitHub Desktop.

Select an option

Save xbalaji/28c2e8963c72070ce431306e0616fdb2 to your computer and use it in GitHub Desktop.
gist-access-download-bookmark
#! /usr/bin/env bash
# Function to download a specific gist file from a user
function get_one_gist() {
local username="$1"
local gist_name="$2"
if [[ -z "$username" || -z "$gist_name" ]]; then
echo "Usage: get_one_gist <username> <gist_name>"
return 1
fi
# Fetch gists and find the specific gist URL
local raw_url
raw_url=$(curl -s "https://api.github.com/users/${username}/gists?per_page=200" \
| jq -r --arg name "$gist_name" '.[] | .files[$name].raw_url // empty')
if [[ -z "$raw_url" ]]; then
echo "Gist '$gist_name' not found for user '$username'."
return 1
fi
# Create directory if needed and download the file
mkdir -p "$username"
curl -s -o "${username}/${gist_name}" "$raw_url"
echo "Downloaded ${gist_name} to ${username}/"
}
#!/usr/bin/env bash
get_public_gists() {
local verbose=false
local show_help=false
local dt
local ix
local uid
local -a github_users=()
_usage() {
cat <<EOF
Invocation:
Standalone:
./gist-get-public-gists.sh [-v|--verbose] xbalaji xbalajipge xbalajiv xb01 xb02 internetmisuser
Sourced:
source ./gist-get-public-gists.sh
get_public_gists [-v|--verbose] xbalaji xbalajipge xbalajiv xb01 xb02 internetmisuser
Usage:
get_public_gists [-h|--help] [-v|--verbose] github-user [github-user ...]
Default command:
get_public_gists xbalaji xbalajipge xbalajiv xb01 xb02 internetmisuser
Options:
-h, --help Show this help
-v, --verbose Print additional details
EOF
}
_usage_short() {
cat <<EOF
Usage:
./gist-get-public-gists.sh xbalaji xbalajipge xbalajiv xb01 xb02 internetmisuser
source ./gist-get-public-gists.sh && get_public_gists xbalaji xbalajipge xbalajiv xb01 xb02 internetmisuser
Use '-h' to print more details.
EOF
}
_confirm_overwrite() {
local prompt_answer
read -r -p "$1 [y/N] " prompt_answer
case "$prompt_answer" in
y|Y|yes|YES)
return 0
;;
*)
return 1
;;
esac
}
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_help=true
shift
;;
-v|--verbose)
verbose=true
shift
;;
--)
shift
break
;;
-*)
echo "Invalid option: $1"
echo
_usage
return 1
;;
*)
github_users+=("$1")
shift
;;
esac
done
while [[ $# -gt 0 ]]; do
github_users+=("$1")
shift
done
if [[ "$show_help" == true ]]; then
_usage
return 0
fi
if [[ ${#github_users[@]} -eq 0 ]]; then
_usage_short
return 1
fi
dt=$(date "+%Y-%m-%d")
for uid in "${github_users[@]}"; do
if [[ -d "gist-${uid}-${dt}" ]]; then
if ! _confirm_overwrite "Directory gist-${uid}-${dt} already exists. Continue"; then
echo "Bailing out."
return 1
fi
fi
done
for uid in "${github_users[@]}"; do
if [[ -d "gist-${uid}-${dt}" ]]; then
if [[ "$verbose" == true ]]; then
echo "Removing existing archive gist-${uid}-${dt}"
fi
rm -rf "gist-${uid}-${dt}"
fi
done
if [[ "$verbose" == true ]]; then
echo "Archiving existing files with suffix: ${dt}"
fi
for uid in "${github_users[@]}"; do
ix="gist-${uid}"
[[ -d "$ix" ]] || continue
if [[ "$verbose" == true ]]; then
echo "Moving ${ix} -> ${ix}-${dt}"
fi
mv "${ix}" "${ix}-${dt}"
done
for uid in "${github_users[@]}"; do
if [[ "$verbose" == true ]]; then
echo "Fetching public gists for ${uid}"
fi
curl -sk -o - "https://api.github.com/users/${uid}/gists?per_page=200" \
| jq -r --arg dx "$uid" '.[].files[]| "-sk --create-dirs -o gist-\($dx)/\(.filename) \(.raw_url)"' \
| xargs -t -L 1 curl
done
for uid in "${github_users[@]}"; do
ix="gist-${uid}"
[[ -d "${ix}-${dt}" ]] || continue
[[ -d "$ix" ]] || continue
echo "diff -wqrB \"${ix}-${dt}\" \"${ix}\""
diff -wqrB "${ix}-${dt}" "${ix}" | sed -e 's,Files,diff -u,g;s,and,,g;s,differ,,g'
done
}
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
get_public_gists "$@"
exit $?
fi
#! /usr/bin/env bash
# Function to display all gists of a user
function get_user_gists() {
local username="$1"
if [[ -z "$username" ]]; then
echo "Usage: get_user_gists <username>"
return 1
fi
# Fetch gists and print their filenames
curl -s "https://api.github.com/users/${username}/gists?per_page=200" \
| jq -r '.[].files | keys[]'
}
export gist_rawurl="https://gist.githubusercontent.com/xbalaji/28c2e8963c72070ce431306e0616fdb2/raw/gist-make-bookmark.sh"
curl -sk "${gist_rawurl}" | sed -e "s,.*<script>,,g;s,</script>$,,g" | js-beautify -s2 | sed -e "1i\<script>" -e "\$a</script>" > in.html
# edit in.html, validate your changes
tr -s " " <in.html | tr -d "\n" | sed -e 's#^#data:text/html,#g;$a\' | tee out.js
# save out.js to "gist-make-bookmark.sh"
data:text/html,<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><script>document.addEventListener("DOMContentLoaded", function() { /* comments has to be single line only */ const mkText = t => document.createTextNode(t); const mkLink = (t, href) => { let anc = document.createElement("a"); anc.setAttribute("href", href); anc.setAttribute("target", "_blank"); anc.textContent = t; return anc; }; function addRow(tr, idata, itransform = mkText, ...transformArgs) { let td = document.createElement("td"); td.appendChild(itransform(idata, ...transformArgs)); tr.appendChild(td); }; function addRowHeader(idata, itransform = mkText, ...transformArgs) { let tr = document.createElement("tr"); for (let cell of idata) { let th = document.createElement("th"); th.appendChild(itransform(cell, ...transformArgs)); th.classList.add("position-sticky"); th.style.top = "0"; tr.appendChild(th); } return tr; }; /* create a table element */ let container = document.createElement("div"); let tbl = document.createElement("table"); let tb = document.createElement("tbody"); let th = document.createElement("thead"); container.classList.add("container", "mt-5"); tbl.classList.add("table", "table-hover", "table-sm", "table-condensed"); th.appendChild(addRowHeader(["S.No", "Raw", "Edit", "URL"])); th.classList.add("thead-dark"); tbl.appendChild(th); tbl.appendChild(tb); container.appendChild(tbl); let sno = 0; fetch("https://api.github.com/users/xbalaji/gists?per_page=150").then(resp => resp.json()).then(gists => { document.body.appendChild(container); let files = gists.flatMap(gist => Object.values(gist.files).map(file => Object.assign(file, { owner: gist.owner.login, id: gist.id, gist_url: gist.html_url, }))); console.log(files); files.sort((file1, file2) => { return file1.filename.localeCompare(file2.filename); }); for (let file of files) { sno += 1; let tr = document.createElement("tr"); addRow(tr, sno.toString().padStart(2, '0')); addRow(tr, "raw", mkLink, file.raw_url); addRow(tr, "edit", mkLink, "https://gist.github.com/" + file.owner + "/" + file.id + "/edit"); addRow(tr, file.filename, mkLink, file.gist_url); tb.appendChild(tr); }; });})</script>
data:text/html,<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><script>document.addEventListener("DOMContentLoaded", function() { let gitUserId = prompt("Enter github id", "xbalaji"); /* comments has to be single line only */ const mkText = t => document.createTextNode(t); const mkLink = (t, href) => { let anc = document.createElement("a"); anc.setAttribute("href", href); anc.setAttribute("target", "_blank"); anc.textContent = t; return anc; }; function addRow(tr, idata, itransform = mkText, ...transformArgs) { let td = document.createElement("td"); td.appendChild(itransform(idata, ...transformArgs)); tr.appendChild(td); }; function addRowHeader(idata, itransform = mkText, ...transformArgs) { let tr = document.createElement("tr"); for (let cell of idata) { let th = document.createElement("th"); th.appendChild(itransform(cell, ...transformArgs)); th.classList.add("position-sticky"); th.style.top = "0"; tr.appendChild(th); } return tr; }; /* create a table element */ let container = document.createElement("div"); let tbl = document.createElement("table"); let tb = document.createElement("tbody"); let th = document.createElement("thead"); container.classList.add("container", "mt-5"); tbl.classList.add("table", "table-hover", "table-sm", "table-condensed"); th.appendChild(addRowHeader(["S.No", "Raw", "Edit", "URL"])); th.classList.add("thead-dark"); tbl.appendChild(th); tbl.appendChild(tb); container.appendChild(tbl); let sno = 0; fetch(`https://api.github.com/users/${gitUserId}/gists?per_page=150`).then(resp => resp.json()).then(gists => { document.body.appendChild(container); let files = gists.flatMap(gist => Object.values(gist.files).map(file => Object.assign(file, { owner: gist.owner.login, id: gist.id, gist_url: gist.html_url, }))); console.log(files); files.sort((file1, file2) => { return file1.filename.localeCompare(file2.filename); }); for (let file of files) { sno += 1; let tr = document.createElement("tr"); addRow(tr, sno.toString().padStart(2, "0")); addRow(tr, "raw", mkLink, file.raw_url); addRow(tr, "edit", mkLink, "https://gist.github.com/" + file.owner + "/" + file.id + "/edit"); addRow(tr, file.filename, mkLink, file.gist_url); tb.appendChild(tr); }; });})</script>
curl -sk "https://api.github.com/users/xbalaji/gists?per_page=100" | jq -r '.[].files[] | [.filename, .raw_url] | @tsv' | sort | column -t --table-columns "FileName,RawUrl"
curl -sk "https://api.github.com/users/xbalaji/gists?per_page=100" | jq -r '.[] | {html_url:.html_url, files:.files[]} | [.files.filename, .html_url] | @tsv' | sort | column -t --table-columns "FileName,HtmlUrl"| nl
curl -sk "https://api.github.com/users/xbalaji/gists?per_page=200" | jq -r '.[].files[].filename' | sort
curl -sk "https://api.github.com/users/xbalaji/gists?per_page=200" | jq -r '.[].files| to_entries[] | .key' | sort
wget -qL -O - "https://api.github.com/users/xbalaji/gists?per_page=100" | jq -r '.[].files[].filename'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment