Christopher Peterson

September 7, 2018

Rclone remote path auto-completion on Linux (Google Drive)



UPDATE: My autocomplete script now ships with Rclone as of version 1.46. So you’re probably better off using that modified, maintained version than this old one here. This post will remain up as a reference. 🙂


I started playing with rclone in the interest of easily editing files from Google Drive with Vim. As it turns out, you can’t edit native Google Docs files in this manner, so that was a wash!

But a side benefit of this misadventure is this bash autocomplete script which I wrote to auto-complete remote paths for Rclone with a Google Drive target. It probably works for others too, I haven’t tested them. :-)

This implementation is in pure bash all except for the call to rclone itself to check against known remote targets. I appreciated An introduction to bash completion to get me started on the concepts, and the rest of what anyone needs is all in the bash manpage under complete.

Here in this post is the initial version I’m using.

# rclone bash autocomplete
# Christopher Peterson [https://cspeterson.net]
# This file provides a bash completion function for autocompleting remote
# Google Drive paths rclone
# It might well work with other cloud services supported by rclone, but I have
# not tested any others.

# Requirements:
#   rclone >= v1.40 # https://rclone.org/install/

# Installation:
#   Cat or copy this script into "${HOME}/.bash_completion", or
#   Copy this script into /etc/bash_completion.d/ for system-wide use
#
# Caveats:
#   Rclone itself also provides some bash autocompletion, though it does not
#   include remote paths. So this should override the other autocompletes, if
#   they are installed. In the future, I'll consider how to perhaps integrate
#   with them in the future.

_rclone_remote_ls() {
  local  foundremote opts remotename remotepath remotes rpath_cur rpath_start
  COMPREPLY=()

	# Since we're dealing with a colon in the remote path, we'll get the
	# current arg this way (colon is a stop character for readline)
	_get_comp_words_by_ref -n : cur

  # Check first that `cur` is an rclone remote in the form of
  # `remotename:words/`.  A slash (or multiple) may or may or may not be present.
  if ! [[ "${cur}" =~ ^[a-zA-Z0-9]*:.*/?.* ]]; then
    return
  fi

  # Split the path at the last slash
  remotename=${cur%:*}
  remotepath=${cur#*\:}

  remotes=($(rclone listremotes | sed 's/:$//g'))

  # Look for a remote drive matching the input
  foundremote=0
  for remote in "${remotes[@]}"; do
    if [ "${remotename}" = "${remote}" ]; then
      foundremote=1
      break
    fi
  done
  if ! [ "${foundremote}" -eq 1 ]; then
    return
  fi

  # If remote path has a slash, we can set up to look in a subdir.
  if [[  "${remotepath}" == */* ]]; then
    rpath_start=${remotepath%/*}
    rpath_cur=${remotepath##*/}
  else
    rpath_start=''
    rpath_cur="${remotepath}"
  fi

  # Create a final array containing matching file paths for bash autocomplete
  opts=()
  while IFS=  read -r line; do
    if [ -z "${rpath_start}" ]; then
      line=("${line}")
    else
      line=("${rpath_start}/${line}")
    fi
    echo "${line}" | grep -P "^${remotepath}" 2>&1 >/dev/null
    if [ "$?" -eq 0 ]; then
      opts+=("${line}")
    fi
  done < <(rclone lsf --max-depth 1 "${remotename}:${rpath_start}" 2>/dev/null)

  COMPREPLY=("${opts[@]}")
  return
}

complete -o filenames -F _rclone_remote_ls rclone