bash utility

edits.sh

Pull remote files over SFTP, edit them locally, and push changes back automatically on save.

What it does

edits.sh connects to a remote server via SFTP, pulls files of a given extension into a local temp directory, and opens them one at a time in your preferred editor. When you save and close a file, it is immediately copied back to the remote. Files closed without saving are skipped. The temp directory is cleaned up on exit.

Usage

01Download the script and make it executable: chmod +x edits.sh
02Optionally install it globally: sudo cp edits.sh /usr/local/bin/edits
03Run it with a remote path: edits user@host:/path/to/dir — or with no argument to be prompted.
04Confirm the file list, then edit each file. Save and close to upload. Close without saving to skip.

Flags

-e ext File extension to pull and edit. Defaults to txt. Pass md, sh, or any other extension.
$EDITOR Respects the $EDITOR environment variable. Defaults to nano if unset.

Source

edits.sh
#!/usr/bin/env bash
# edits.sh - pull remote files, edit locally, push back on save
# chmod +x edits.sh - make script executable
# sudo cp edits.sh /usr/local/bin/edits
# credit - barney matthews (www.barney.me)

set -euo pipefail

EDITOR="${EDITOR:-nano}"
EXT="txt"

# Parse flags
while [[ $# -gt 0 ]]; do
  case "$1" in
    -e) EXT="$2"; shift 2 ;;
    *)  REMOTE="$1"; shift ;;
  esac
done

echo ""
echo "edits.sh  [-e ext] [user@host:/path]"
echo "  -e ext  File extension to edit (default: txt)"
echo "  Save and close a file to upload it. Close without saving to skip."
echo ""

# Prompt if no remote provided
if [[ -z "${REMOTE:-}" ]]; then
  read -rp "Remote path (user@host:/path/to/dir): " REMOTE
fi

REMOTE_HOST="${REMOTE%%:*}"
REMOTE_PATH="${REMOTE#*:}"

TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT

echo "Pulling .$EXT files from $REMOTE_HOST:$REMOTE_PATH ..."
sftp -q "$REMOTE_HOST" <<SFTP
lcd "$TMPDIR"
cd "$REMOTE_PATH"
mget *.$EXT
SFTP

FILES=("$TMPDIR"/*."$EXT")
if [[ ! -e "${FILES[0]}" ]]; then
  echo "No .$EXT files found." >&2
  exit 1
fi

echo "Found ${#FILES[@]} file(s): $(basename -a "${FILES[@]}" | tr '\n' ' ')"
echo ""

# Confirm before editing
read -rp "Edit these files? [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
  echo "Aborted."
  exit 0
fi
echo ""

# Edit each file, upload immediately on save+close
for f in "${FILES[@]}"; do
  NAME="$(basename "$f")"
  MTIME_BEFORE="$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f")"

  "$EDITOR" "$f"

  MTIME_AFTER="$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f")"

  if [[ "$MTIME_BEFORE" != "$MTIME_AFTER" ]]; then
    echo "Uploading $NAME ..."
    sftp -q "$REMOTE_HOST" <<SFTP
cd "$REMOTE_PATH"
put "$f"
SFTP
    echo "Done."
  else
    echo "No changes to $NAME, skipping."
  fi
  echo ""
done