#!/bin/bash
# Securily download a clean copy of the latest pip.
# Then find virtual environments and inspect or update.
# Use environ variable APPLY=1 to trigger updates.
wheel="$HOME/Downloads/pip-26.2.2-py3-none-any.whl"
url="https://files.pythonhosted.org/packages/3f/06/3e4420302363fbb71be3c7f35ce042f54bfca330e3e66b3a2e3c4cca579f/pip-26.2.2-py3-none-any.whl"
hash="fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70"
# Download once
if [[ ! -f "$wheel" ]]; then
echo "Downloading pip 26.2.2..."
curl -fLsS --output "$wheel" "$url" || exit 1
fi
echo "Verifying wheel checksum..."
printf '%s %s\n' "$hash" "$wheel" |
shasum -a 256 --check || exit 1
# Use 'fd' if available, otherwise use 'find'
find_venvs() (
if command -v fd >/dev/null 2>&1; then
echo "Searching with fd..." >&2
fd --hidden --no-ignore --type f \
--glob pyvenv.cfg --print0 "$HOME"
else
echo "Searching with find..." >&2
shopt -s dotglob nullglob
if [[ -f "$HOME/pyvenv.cfg" && ! -L "$HOME/pyvenv.cfg" ]]; then
printf '%s\0' "$HOME/pyvenv.cfg"
fi
for dir in "$HOME"/*; do
[[ -d "$dir" && ! -L "$dir" ]] || continue
echo "Scanning $dir..." >&2
find "$dir" -type f -name pyvenv.cfg \
-print0 2>/dev/null
done
fi
)
echo "Searching for virtual environments under $HOME..."
count=0
failed=0
while IFS= read -r -d '' cfg; do
python="${cfg%/pyvenv.cfg}/bin/python"
[[ -x "$python" ]] || continue
echo "Checking $python..." >&2
version=$("$python" -I -m pip --version 2>/dev/null) ||
continue
count=$((count + 1))
printf '[%d] %s\n %s\n' "$count" "$python" "$version"
if [[ "${APPLY:-0}" == 1 ]]; then
if ! "$python" -I -c \
'import sys; sys.exit(sys.version_info < (3, 10))'; then
echo " SKIPPED: Python older than 3.10"
elif ! "$python" -I -m pip --isolated \
--disable-pip-version-check install \
--no-index --no-deps --upgrade "$wheel"; then
echo " FAILED: $python" >&2
failed=$((failed + 1))
fi
fi
done < <(find_venvs)
echo
echo "Finished: $count pip installations found, $failed upgrades failed."
(( failed == 0 ))
5 Likes