diff --git a/README.md b/README.md
index 2518ca6..17d0af9 100755
--- a/README.md
+++ b/README.md
@@ -502,6 +502,22 @@ These are the custom flags that are currently implemented:
---
+- -desc | --description | --description-all 'description'
+
+ Specify description for the given file.
+
+ To use the respective metadata of a file, below is the format:
+
+ File name ( fullname ): %f
+ Size: %s
+ Mime Type: %m
+
+ Now to actually use it: `--description 'Filename: %f, Size: %s, Mime: %m'`
+
+ Note: For files inside folders, use `--description-all` flag.
+
+ ---
+
- -d | --skip-duplicates
Do not upload the files with the same name, if already present in the root folder/input folder, also works with recursive folders.
diff --git a/bash/common-utils.bash b/bash/common-utils.bash
index 13eb3a9..347c62e 100755
--- a/bash/common-utils.bash
+++ b/bash/common-utils.bash
@@ -189,6 +189,30 @@ _get_latest_sha() {
printf "%b" "${LATEST_SHA:+${LATEST_SHA}\n}"
}
+###################################################
+# Encode the given string to parse properly as json
+# Globals: None
+# Arguments: 1
+# ${1} = string
+# Result: print encoded string
+# Reference:
+# https://tools.ietf.org/html/rfc7159#section-7
+###################################################
+_json_escape() {
+ declare input="${1:?Provide Input}"
+ : "${input//\\/\\\\}" \
+ : "${_//\//\\\/}" # \
+ # /
+ : "${_//\'/\\\'}" # ' (not strictly needed ?)
+ : "${_//\"/\\\"}" # "
+ : "${_//$'\t'/\\\t}" # \t (tab)
+ : "${_//$'\n'/\\\n}" # \n (newline)
+ : "${_//$'\r'/\\\r}" # \r (carriage return)
+ : "${_//$'\f'/\\\f}" # \f (form feed)
+ : "${_//$'\b'/\\\b}" # \b (backspace)
+ printf "%s" "${_}"
+}
+
###################################################
# Method to extract specified field data from json
# Globals: None
@@ -386,6 +410,7 @@ ALL_FUNCTIONS=(_bytes_to_human
_dirname
_display_time
_get_latest_sha
+ _json_escape
_json_value
_print_center
_print_center_quiet
diff --git a/bash/drive-utils.bash b/bash/drive-utils.bash
index dd0f787..3ff5afa 100755
--- a/bash/drive-utils.bash
+++ b/bash/drive-utils.bash
@@ -30,7 +30,7 @@ _check_existing_file() {
###################################################
# Copy/Clone a public gdrive file/folder from another/same gdrive account
# Globals: 6 variables, 2 functions
-# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _print_center, _check_existing_file, _json_value, _bytes_to_human, _clear_line
# Arguments: 5
# ${1} = update or upload ( upload type )
@@ -47,10 +47,17 @@ _check_existing_file() {
_clone_file() {
[[ $# -lt 5 ]] && printf "%s: Missing arguments\n" "${FUNCNAME[0]}" && return 1
declare job="${1}" file_id="${2}" file_root_id="${3}" name="${4}" size="${5}"
- declare clone_file_post_data clone_file_response readable_size _file_id && STRING="Cloned"
- clone_file_post_data="{\"parents\": [\"${file_root_id}\"]}"
+ declare clone_file_post_data clone_file_response readable_size _file_id description && STRING="Cloned"
readable_size="$(_bytes_to_human "${size}")"
+ # create description data
+ [[ -n ${DESCRIPTION_FILE} ]] && {
+ : "${DESCRIPTION_FILE//%f/${name}}" && : "${_//%s/${readable_size}}"
+ description="$(_json_escape "${_}")" # escape for json
+ }
+
+ clone_file_post_data="{\"parents\": [\"${file_root_id}\"]${description:+,\"description\":\"${description}\"}}"
+
_print_center "justify" "${name} " "| ${readable_size}" "="
if [[ ${job} = update ]]; then
@@ -181,7 +188,7 @@ _extract_id() {
# Upload ( Create/Update ) files on gdrive.
# Interrupted uploads can be resumed.
# Globals: 8 variables, 10 functions
-# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _url_encode, _json_value, _print_center, _bytes_to_human
# _generate_upload_link, _upload_file_from_uri, _log_upload_session, _remove_upload_session
# _full_upload, _collect_file_info
@@ -200,7 +207,8 @@ _extract_id() {
_upload_file() {
[[ $# -lt 3 ]] && printf "%s: Missing arguments\n" "${FUNCNAME[0]}" && return 1
declare job="${1}" input="${2}" folder_id="${3}" \
- slug inputname extension inputsize readable_size request_method url postdata uploadlink upload_body mime_type resume_args1 resume_args2 resume_args3
+ slug inputname extension inputsize readable_size request_method url postdata uploadlink upload_body mime_type description \
+ resume_args1 resume_args2 resume_args3
slug="${input##*/}"
inputname="${slug%.*}"
@@ -216,6 +224,12 @@ _upload_file() {
}
}
+ # create description data
+ [[ -n ${DESCRIPTION_FILE} ]] && {
+ : "${DESCRIPTION_FILE//%f/${slug}}" && : "${_//%s/${inputsize}}" && : "${_//%m/${mime_type}}"
+ description="$(_json_escape "${_}")" # escape for json
+ }
+
_print_center "justify" "${input##*/}" " | ${readable_size}" "="
# Set proper variables for overwriting files
@@ -234,7 +248,7 @@ _upload_file() {
{ _error_logging_upload "${slug}" "${file_check_json}" || return 1; }
url="${API_URL}/upload/drive/${API_VERSION}/files/${_file_id}?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
# JSON post data to specify the file name and folder under while the file to be updated
- postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"addParents\": [\"${folder_id}\"]}"
+ postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"addParents\": [\"${folder_id}\"]${description:+,\"description\":\"${description}\"}}"
STRING="Updated"
fi
else
@@ -247,7 +261,7 @@ _upload_file() {
url="${API_URL}/upload/drive/${API_VERSION}/files?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
request_method="POST"
# JSON post data to specify the file name and folder under while the file to be created
- postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"parents\": [\"${folder_id}\"]}"
+ postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"parents\": [\"${folder_id}\"]${description:+,\"description\":\"${description}\"}}"
STRING="Uploaded"
}
diff --git a/bash/release/gsync b/bash/release/gsync
index a8dded1..ba701f7 100755
--- a/bash/release/gsync
+++ b/bash/release/gsync
@@ -190,6 +190,30 @@ _get_latest_sha() {
printf "%b" "${LATEST_SHA:+${LATEST_SHA}\n}"
}
+###################################################
+# Encode the given string to parse properly as json
+# Globals: None
+# Arguments: 1
+# ${1} = string
+# Result: print encoded string
+# Reference:
+# https://tools.ietf.org/html/rfc7159#section-7
+###################################################
+_json_escape() {
+ declare input="${1:?Provide Input}"
+ : "${input//\\/\\\\}" \
+ : "${_//\//\\\/}" # \
+ # /
+ : "${_//\'/\\\'}" # ' (not strictly needed ?)
+ : "${_//\"/\\\"}" # "
+ : "${_//$'\t'/\\\t}" # \t (tab)
+ : "${_//$'\n'/\\\n}" # \n (newline)
+ : "${_//$'\r'/\\\r}" # \r (carriage return)
+ : "${_//$'\f'/\\\f}" # \f (form feed)
+ : "${_//$'\b'/\\\b}" # \b (backspace)
+ printf "%s" "${_}"
+}
+
###################################################
# Method to extract specified field data from json
# Globals: None
@@ -387,6 +411,7 @@ ALL_FUNCTIONS=(_bytes_to_human
_dirname
_display_time
_get_latest_sha
+ _json_escape
_json_value
_print_center
_print_center_quiet
diff --git a/bash/release/gupload b/bash/release/gupload
index 830e7ac..a6d61ef 100755
--- a/bash/release/gupload
+++ b/bash/release/gupload
@@ -190,6 +190,30 @@ _get_latest_sha() {
printf "%b" "${LATEST_SHA:+${LATEST_SHA}\n}"
}
+###################################################
+# Encode the given string to parse properly as json
+# Globals: None
+# Arguments: 1
+# ${1} = string
+# Result: print encoded string
+# Reference:
+# https://tools.ietf.org/html/rfc7159#section-7
+###################################################
+_json_escape() {
+ declare input="${1:?Provide Input}"
+ : "${input//\\/\\\\}" \
+ : "${_//\//\\\/}" # \
+ # /
+ : "${_//\'/\\\'}" # ' (not strictly needed ?)
+ : "${_//\"/\\\"}" # "
+ : "${_//$'\t'/\\\t}" # \t (tab)
+ : "${_//$'\n'/\\\n}" # \n (newline)
+ : "${_//$'\r'/\\\r}" # \r (carriage return)
+ : "${_//$'\f'/\\\f}" # \f (form feed)
+ : "${_//$'\b'/\\\b}" # \b (backspace)
+ printf "%s" "${_}"
+}
+
###################################################
# Method to extract specified field data from json
# Globals: None
@@ -387,6 +411,7 @@ ALL_FUNCTIONS=(_bytes_to_human
_dirname
_display_time
_get_latest_sha
+ _json_escape
_json_value
_print_center
_print_center_quiet
@@ -929,7 +954,7 @@ _check_existing_file() {
###################################################
# Copy/Clone a public gdrive file/folder from another/same gdrive account
# Globals: 6 variables, 2 functions
-# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _print_center, _check_existing_file, _json_value, _bytes_to_human, _clear_line
# Arguments: 5
# ${1} = update or upload ( upload type )
@@ -946,10 +971,17 @@ _check_existing_file() {
_clone_file() {
[[ $# -lt 5 ]] && printf "%s: Missing arguments\n" "${FUNCNAME[0]}" && return 1
declare job="${1}" file_id="${2}" file_root_id="${3}" name="${4}" size="${5}"
- declare clone_file_post_data clone_file_response readable_size _file_id && STRING="Cloned"
- clone_file_post_data="{\"parents\": [\"${file_root_id}\"]}"
+ declare clone_file_post_data clone_file_response readable_size _file_id description && STRING="Cloned"
readable_size="$(_bytes_to_human "${size}")"
+ # create description data
+ [[ -n ${DESCRIPTION_FILE} ]] && {
+ : "${DESCRIPTION_FILE//%f/${name}}" && : "${_//%s/${readable_size}}"
+ description="$(_json_escape "${_}")" # escape for json
+ }
+
+ clone_file_post_data="{\"parents\": [\"${file_root_id}\"]${description:+,\"description\":\"${description}\"}}"
+
_print_center "justify" "${name} " "| ${readable_size}" "="
if [[ ${job} = update ]]; then
@@ -1080,7 +1112,7 @@ _extract_id() {
# Upload ( Create/Update ) files on gdrive.
# Interrupted uploads can be resumed.
# Globals: 8 variables, 10 functions
-# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _url_encode, _json_value, _print_center, _bytes_to_human
# _generate_upload_link, _upload_file_from_uri, _log_upload_session, _remove_upload_session
# _full_upload, _collect_file_info
@@ -1099,7 +1131,8 @@ _extract_id() {
_upload_file() {
[[ $# -lt 3 ]] && printf "%s: Missing arguments\n" "${FUNCNAME[0]}" && return 1
declare job="${1}" input="${2}" folder_id="${3}" \
- slug inputname extension inputsize readable_size request_method url postdata uploadlink upload_body mime_type resume_args1 resume_args2 resume_args3
+ slug inputname extension inputsize readable_size request_method url postdata uploadlink upload_body mime_type description \
+ resume_args1 resume_args2 resume_args3
slug="${input##*/}"
inputname="${slug%.*}"
@@ -1115,6 +1148,12 @@ _upload_file() {
}
}
+ # create description data
+ [[ -n ${DESCRIPTION_FILE} ]] && {
+ : "${DESCRIPTION_FILE//%f/${slug}}" && : "${_//%s/${inputsize}}" && : "${_//%m/${mime_type}}"
+ description="$(_json_escape "${_}")" # escape for json
+ }
+
_print_center "justify" "${input##*/}" " | ${readable_size}" "="
# Set proper variables for overwriting files
@@ -1133,7 +1172,7 @@ _upload_file() {
{ _error_logging_upload "${slug}" "${file_check_json}" || return 1; }
url="${API_URL}/upload/drive/${API_VERSION}/files/${_file_id}?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
# JSON post data to specify the file name and folder under while the file to be updated
- postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"addParents\": [\"${folder_id}\"]}"
+ postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"addParents\": [\"${folder_id}\"]${description:+,\"description\":\"${description}\"}}"
STRING="Updated"
fi
else
@@ -1146,7 +1185,7 @@ _upload_file() {
url="${API_URL}/upload/drive/${API_VERSION}/files?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
request_method="POST"
# JSON post data to specify the file name and folder under while the file to be created
- postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"parents\": [\"${folder_id}\"]}"
+ postdata="{\"mimeType\": \"${mime_type}\",\"name\": \"${slug}\",\"parents\": [\"${folder_id}\"]${description:+,\"description\":\"${description}\"}}"
STRING="Uploaded"
}
@@ -1509,6 +1548,10 @@ Options:\n
-f | --[file|folder] - Specify files and folders explicitly in one command, use multiple times for multiple folder/files. See README for more use of this command.\n
-cl | --clone - Upload a gdrive file without downloading, require accessible gdrive link or id as argument.\n
-o | --overwrite - Overwrite the files with the same name, if present in the root folder/input folder, also works with recursive folders.\n
+ -desc | --description | --description-all - Specify description for the given file. To use the respective metadata of a file, below is the format:\n
+ File name ( fullname ): %f | Size: %s | Mime Type: %m\n
+ Now to actually use it: --description 'Filename: %f, Size: %s, Mime: %m'\n
+ Note: For files inside folders, use --description-all flag.\n
-d | --skip-duplicates - Do not upload the files with the same name, if already present in the root folder/input folder, also works with recursive folders.\n
-S | --share - Share the uploaded input file/folder, grant reader permission to provided email address or to everyone with the shareable link.\n
--speed 'speed' - Limit the download speed, supported formats: 1K, 1M and 1G.\n
@@ -1603,7 +1646,7 @@ _setup_arguments() {
# De-initialize if any variables set already.
unset LIST_ACCOUNTS UPDATE_DEFAULT_ACCOUNT CUSTOM_ACCOUNT_NAME NEW_ACCOUNT_NAME DELETE_ACCOUNT_NAME ACCOUNT_ONLY_RUN
unset FOLDERNAME LOCAL_INPUT_ARRAY ID_INPUT_ARRAY CONTINUE_WITH_NO_INPUT
- unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES SKIP_SUBDIRS ROOTDIR QUIET
+ unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES DESCRIPTION SKIP_SUBDIRS ROOTDIR QUIET
unset VERBOSE VERBOSE_PROGRESS DEBUG LOG_FILE_ID CURL_SPEED RETRY
export CURL_PROGRESS="-s" EXTRA_LOG=":" CURL_PROGRESS_EXTRA="-s"
INFO_PATH="${HOME}/.google-drive-upload" CONFIG_INFO="${INFO_PATH}/google-drive-upload.configpath"
@@ -1686,6 +1729,11 @@ _setup_arguments() {
;;
-o | --overwrite) export OVERWRITE="Overwrite" UPLOAD_MODE="update" ;;
-d | --skip-duplicates) export SKIP_DUPLICATES="Skip Existing" UPLOAD_MODE="update" ;;
+ -desc | --description | --description-all)
+ _check_longoptions "${1}" "${2}"
+ [[ ${1} = "--description-all" ]] && export DESCRIPTION_ALL="true"
+ export DESCRIPTION="${2}" && shift
+ ;;
-f | --file | --folder)
_check_longoptions "${1}" "${2}"
LOCAL_INPUT_ARRAY+=("${2}") && shift
@@ -1903,6 +1951,9 @@ _process_arguments() {
for input in "${FINAL_LOCAL_INPUT_ARRAY[@]}"; do
# Check if the argument is a file or a directory.
if [[ -f ${input} ]]; then
+ # export DESCRIPTION_FILE, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": FILE" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_upload_file_main noparse "${input}" "${WORKSPACE_FOLDER_ID}"
@@ -1916,6 +1967,9 @@ _process_arguments() {
input="$(cd "${input}" && pwd)" || return 1 # to handle _dirname when current directory (.) is given as input.
unset EMPTY # Used when input folder is empty
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL:+${DESCRIPTION}}"
+
_print_center "justify" "Given Input" ": FOLDER" "-"
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
FOLDER_NAME="${input##*/}" && "${EXTRA_LOG}" "justify" "Folder: ${FOLDER_NAME}" "="
@@ -2039,9 +2093,15 @@ _process_arguments() {
size="$(_json_value size 1 1 <<< "${json}" || :)"
for _ in 1 2; do _clear_line 1; done
if [[ ${type} =~ folder ]]; then
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL+:${DESCRIPTION}}"
+
"${QUIET:-_print_center}" "justify" "Folder not supported." "=" 1>&2 && _newline "\n" 1>&2 && continue
## TODO: Add support to clone folders
else
+ # export DESCRIPTION_FILE, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": File ID" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_clone_file "${UPLOAD_MODE:-create}" "${gdrive_id}" "${WORKSPACE_FOLDER_ID}" "${name}" "${size}" ||
diff --git a/bash/upload.bash b/bash/upload.bash
index 3eeafe5..dad310d 100755
--- a/bash/upload.bash
+++ b/bash/upload.bash
@@ -22,6 +22,10 @@ Options:\n
-f | --[file|folder] - Specify files and folders explicitly in one command, use multiple times for multiple folder/files. See README for more use of this command.\n
-cl | --clone - Upload a gdrive file without downloading, require accessible gdrive link or id as argument.\n
-o | --overwrite - Overwrite the files with the same name, if present in the root folder/input folder, also works with recursive folders.\n
+ -desc | --description | --description-all - Specify description for the given file. To use the respective metadata of a file, below is the format:\n
+ File name ( fullname ): %f | Size: %s | Mime Type: %m\n
+ Now to actually use it: --description 'Filename: %f, Size: %s, Mime: %m'\n
+ Note: For files inside folders, use --description-all flag.\n
-d | --skip-duplicates - Do not upload the files with the same name, if already present in the root folder/input folder, also works with recursive folders.\n
-S | --share - Share the uploaded input file/folder, grant reader permission to provided email address or to everyone with the shareable link.\n
--speed 'speed' - Limit the download speed, supported formats: 1K, 1M and 1G.\n
@@ -116,7 +120,7 @@ _setup_arguments() {
# De-initialize if any variables set already.
unset LIST_ACCOUNTS UPDATE_DEFAULT_ACCOUNT CUSTOM_ACCOUNT_NAME NEW_ACCOUNT_NAME DELETE_ACCOUNT_NAME ACCOUNT_ONLY_RUN
unset FOLDERNAME LOCAL_INPUT_ARRAY ID_INPUT_ARRAY CONTINUE_WITH_NO_INPUT
- unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES SKIP_SUBDIRS ROOTDIR QUIET
+ unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES DESCRIPTION SKIP_SUBDIRS ROOTDIR QUIET
unset VERBOSE VERBOSE_PROGRESS DEBUG LOG_FILE_ID CURL_SPEED RETRY
export CURL_PROGRESS="-s" EXTRA_LOG=":" CURL_PROGRESS_EXTRA="-s"
INFO_PATH="${HOME}/.google-drive-upload" CONFIG_INFO="${INFO_PATH}/google-drive-upload.configpath"
@@ -199,6 +203,11 @@ _setup_arguments() {
;;
-o | --overwrite) export OVERWRITE="Overwrite" UPLOAD_MODE="update" ;;
-d | --skip-duplicates) export SKIP_DUPLICATES="Skip Existing" UPLOAD_MODE="update" ;;
+ -desc | --description | --description-all)
+ _check_longoptions "${1}" "${2}"
+ [[ ${1} = "--description-all" ]] && export DESCRIPTION_ALL="true"
+ export DESCRIPTION="${2}" && shift
+ ;;
-f | --file | --folder)
_check_longoptions "${1}" "${2}"
LOCAL_INPUT_ARRAY+=("${2}") && shift
@@ -416,6 +425,9 @@ _process_arguments() {
for input in "${FINAL_LOCAL_INPUT_ARRAY[@]}"; do
# Check if the argument is a file or a directory.
if [[ -f ${input} ]]; then
+ # export DESCRIPTION_FILE, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": FILE" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_upload_file_main noparse "${input}" "${WORKSPACE_FOLDER_ID}"
@@ -429,6 +441,9 @@ _process_arguments() {
input="$(cd "${input}" && pwd)" || return 1 # to handle _dirname when current directory (.) is given as input.
unset EMPTY # Used when input folder is empty
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL:+${DESCRIPTION}}"
+
_print_center "justify" "Given Input" ": FOLDER" "-"
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
FOLDER_NAME="${input##*/}" && "${EXTRA_LOG}" "justify" "Folder: ${FOLDER_NAME}" "="
@@ -552,9 +567,15 @@ _process_arguments() {
size="$(_json_value size 1 1 <<< "${json}" || :)"
for _ in 1 2; do _clear_line 1; done
if [[ ${type} =~ folder ]]; then
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL+:${DESCRIPTION}}"
+
"${QUIET:-_print_center}" "justify" "Folder not supported." "=" 1>&2 && _newline "\n" 1>&2 && continue
## TODO: Add support to clone folders
else
+ # export DESCRIPTION_FILE, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": File ID" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_clone_file "${UPLOAD_MODE:-create}" "${gdrive_id}" "${WORKSPACE_FOLDER_ID}" "${name}" "${size}" ||
diff --git a/sh/drive-utils.sh b/sh/drive-utils.sh
index e49d378..86a8400 100755
--- a/sh/drive-utils.sh
+++ b/sh/drive-utils.sh
@@ -31,7 +31,7 @@ _check_existing_file() (
###################################################
# Copy/Clone a public gdrive file/folder from another/same gdrive account
# Globals: 6 variables, 2 functions
-# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _print_center, _check_existing_file, _json_value, _bytes_to_human, _clear_line
# Arguments: 5
# ${1} = update or upload ( upload type )
@@ -48,10 +48,17 @@ _check_existing_file() (
_clone_file() {
[ $# -lt 5 ] && printf "Missing arguments\n" && return 1
job_clone_file="${1}" file_id_clone_file="${2}" file_root_id_clone_file="${3}" name_clone_file="${4}" size_clone_file="${5}"
- unset post_data_clone_file response_clone_file readable_size_clone_file && STRING="Cloned"
- post_data_clone_file="{\"parents\": [\"${file_root_id_clone_file}\"]}"
+ unset post_data_clone_file response_clone_file readable_size_clone_file description_clone_file && STRING="Cloned"
readable_size_clone_file="$(printf "%s\n" "${size_clone_file}" | _bytes_to_human)"
+ # create description data
+ [ -n "${DESCRIPTION_FILE}" ] && {
+ description_clone_file="$(printf "%s\n" "${DESCRIPTION_FILE}" | sed -e "s|%f|${name_clone_file}|g|" -e "s|%f|${readable_size_clone_file}|g|")"
+ description_clone_file="$(_json_escape "${description_clone_file}")" # escape for json
+ }
+
+ post_data_clone_file="{\"parents\": [\"${file_root_id_clone_file}\"]${description_clone_file:+,\"description\":\"${description_clone_file}\"}}"
+
_print_center "justify" "${name_clone_file} " "| ${readable_size_clone_file}" "="
if [ "${job_clone_file}" = update ]; then
@@ -184,7 +191,7 @@ _extract_id() {
# Upload ( Create/Update ) files on gdrive.
# Interrupted uploads can be resumed.
# Globals: 8 variables, 10 functions
-# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _url_encode, _json_value, _print_center, _bytes_to_human
# _generate_upload_link, _upload_file_from_uri, _log_upload_session, _remove_upload_session
# _full_upload, _collect_file_info
@@ -204,7 +211,8 @@ _upload_file() {
[ $# -lt 3 ] && printf "Missing arguments\n" && return 1
job_upload_file="${1}" input_upload_file="${2}" folder_id_upload_file="${3}"
unset slug_upload_file inputname_upload_file extension_upload_file inputsize_upload_file readable_size_upload_file request_method_upload_file \
- url_upload_file postdata_upload_file uploadlink_upload_file upload_body_upload_file mime_type_upload_file resume_args_upload_file
+ url_upload_file postdata_upload_file uploadlink_upload_file upload_body_upload_file mime_type_upload_file resume_args_upload_file \
+ description_upload_file
slug_upload_file="${input_upload_file##*/}"
inputname_upload_file="${slug_upload_file%.*}"
@@ -220,6 +228,12 @@ _upload_file() {
}
}
+ # create description data
+ [ -n "${DESCRIPTION_FILE}" ] && {
+ description_upload_file="$(printf "%s\n" "${DESCRIPTION_FILE}" | sed -e "s|%f|${slug_upload_file}|g|" -e "s|%f|${readable_size_upload_file}|g|" -e "s|%m|${mime_type_upload_file}|g|")"
+ description_upload_file="$(_json_escape "${description_upload_file}")" # escape for json
+ }
+
_print_center "justify" "${slug_upload_file}" " | ${readable_size_upload_file}" "="
# Set proper variables for overwriting files
@@ -238,7 +252,7 @@ _upload_file() {
{ _error_logging_upload "${slug_upload_file}" "${file_check_json_upload_file}" || return 1; }
url_upload_file="${API_URL}/upload/drive/${API_VERSION}/files/${_file_id_upload_file}?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
# JSON post data to specify the file name and folder under while the file to be updated
- postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"addParents\": [\"${folder_id_upload_file}\"]}"
+ postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"addParents\": [\"${folder_id_upload_file}\"]${description_upload_file:+,\"description\":\"${description_upload_file}\"}}"
STRING="Updated"
fi
else
@@ -251,7 +265,7 @@ _upload_file() {
url_upload_file="${API_URL}/upload/drive/${API_VERSION}/files?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
request_method_upload_file="POST"
# JSON post data to specify the file name and folder under while the file to be created
- postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"parents\": [\"${folder_id_upload_file}\"]}"
+ postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"parents\": [\"${folder_id_upload_file}\"]${description_upload_file:+,\"description\":\"${description_upload_file}\"}}"
STRING="Uploaded"
}
diff --git a/sh/release/gupload b/sh/release/gupload
index 1a2e6e0..017db68 100755
--- a/sh/release/gupload
+++ b/sh/release/gupload
@@ -872,7 +872,7 @@ _check_existing_file() (
###################################################
# Copy/Clone a public gdrive file/folder from another/same gdrive account
# Globals: 6 variables, 2 functions
-# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, CURL_PROGRESS, LOG_FILE_ID, QUIET, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _print_center, _check_existing_file, _json_value, _bytes_to_human, _clear_line
# Arguments: 5
# ${1} = update or upload ( upload type )
@@ -889,10 +889,17 @@ _check_existing_file() (
_clone_file() {
[ $# -lt 5 ] && printf "Missing arguments\n" && return 1
job_clone_file="${1}" file_id_clone_file="${2}" file_root_id_clone_file="${3}" name_clone_file="${4}" size_clone_file="${5}"
- unset post_data_clone_file response_clone_file readable_size_clone_file && STRING="Cloned"
- post_data_clone_file="{\"parents\": [\"${file_root_id_clone_file}\"]}"
+ unset post_data_clone_file response_clone_file readable_size_clone_file description_clone_file && STRING="Cloned"
readable_size_clone_file="$(printf "%s\n" "${size_clone_file}" | _bytes_to_human)"
+ # create description data
+ [ -n "${DESCRIPTION_FILE}" ] && {
+ description_clone_file="$(printf "%s\n" "${DESCRIPTION_FILE}" | sed -e "s|%f|${name_clone_file}|g|" -e "s|%f|${readable_size_clone_file}|g|")"
+ description_clone_file="$(_json_escape "${description_clone_file}")" # escape for json
+ }
+
+ post_data_clone_file="{\"parents\": [\"${file_root_id_clone_file}\"]${description_clone_file:+,\"description\":\"${description_clone_file}\"}}"
+
_print_center "justify" "${name_clone_file} " "| ${readable_size_clone_file}" "="
if [ "${job_clone_file}" = update ]; then
@@ -1025,7 +1032,7 @@ _extract_id() {
# Upload ( Create/Update ) files on gdrive.
# Interrupted uploads can be resumed.
# Globals: 8 variables, 10 functions
-# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN
+# Variables - API_URL, API_VERSION, QUIET, VERBOSE, VERBOSE_PROGRESS, CURL_PROGRESS, LOG_FILE_ID, ACCESS_TOKEN, DESCRIPTION_FILE
# Functions - _url_encode, _json_value, _print_center, _bytes_to_human
# _generate_upload_link, _upload_file_from_uri, _log_upload_session, _remove_upload_session
# _full_upload, _collect_file_info
@@ -1045,7 +1052,8 @@ _upload_file() {
[ $# -lt 3 ] && printf "Missing arguments\n" && return 1
job_upload_file="${1}" input_upload_file="${2}" folder_id_upload_file="${3}"
unset slug_upload_file inputname_upload_file extension_upload_file inputsize_upload_file readable_size_upload_file request_method_upload_file \
- url_upload_file postdata_upload_file uploadlink_upload_file upload_body_upload_file mime_type_upload_file resume_args_upload_file
+ url_upload_file postdata_upload_file uploadlink_upload_file upload_body_upload_file mime_type_upload_file resume_args_upload_file \
+ description_upload_file
slug_upload_file="${input_upload_file##*/}"
inputname_upload_file="${slug_upload_file%.*}"
@@ -1061,6 +1069,12 @@ _upload_file() {
}
}
+ # create description data
+ [ -n "${DESCRIPTION_FILE}" ] && {
+ description_upload_file="$(printf "%s\n" "${DESCRIPTION_FILE}" | sed -e "s|%f|${slug_upload_file}|g|" -e "s|%f|${readable_size_upload_file}|g|" -e "s|%m|${mime_type_upload_file}|g|")"
+ description_upload_file="$(_json_escape "${description_upload_file}")" # escape for json
+ }
+
_print_center "justify" "${slug_upload_file}" " | ${readable_size_upload_file}" "="
# Set proper variables for overwriting files
@@ -1079,7 +1093,7 @@ _upload_file() {
{ _error_logging_upload "${slug_upload_file}" "${file_check_json_upload_file}" || return 1; }
url_upload_file="${API_URL}/upload/drive/${API_VERSION}/files/${_file_id_upload_file}?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
# JSON post data to specify the file name and folder under while the file to be updated
- postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"addParents\": [\"${folder_id_upload_file}\"]}"
+ postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"addParents\": [\"${folder_id_upload_file}\"]${description_upload_file:+,\"description\":\"${description_upload_file}\"}}"
STRING="Updated"
fi
else
@@ -1092,7 +1106,7 @@ _upload_file() {
url_upload_file="${API_URL}/upload/drive/${API_VERSION}/files?uploadType=resumable&supportsAllDrives=true&includeItemsFromAllDrives=true"
request_method_upload_file="POST"
# JSON post data to specify the file name and folder under while the file to be created
- postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"parents\": [\"${folder_id_upload_file}\"]}"
+ postdata_upload_file="{\"mimeType\": \"${mime_type_upload_file}\",\"name\": \"${slug_upload_file}\",\"parents\": [\"${folder_id_upload_file}\"]${description_upload_file:+,\"description\":\"${description_upload_file}\"}}"
STRING="Uploaded"
}
@@ -1436,6 +1450,10 @@ Options:\n
-f | --[file|folder] - Specify files and folders explicitly in one command, use multiple times for multiple folder/files. See README for more use of this command.\n
-cl | --clone - Upload a gdrive file without downloading, require accessible gdrive link or id as argument.\n
-o | --overwrite - Overwrite the files with the same name, if present in the root folder/input folder, also works with recursive folders.\n
+ -desc | --description | --description-all - Specify description for the given file. To use the respective metadata of a file, below is the format:\n
+ File name ( fullname ): %f | Size: %s | Mime Type: %m\n
+ Now to actually use it: --description 'Filename: %f, Size: %s, Mime: %m'\n
+ Note: For files inside folders, use --description-all flag.\n
-d | --skip-duplicates - Do not upload the files with the same name, if already present in the root folder/input folder, also works with recursive folders.\n
-S | --share - Share the uploaded input file/folder, grant reader permission to provided email address or to everyone with the shareable link.\n
--speed 'speed' - Limit the download speed, supported formats: 1K, 1M and 1G.\n
@@ -1532,7 +1550,7 @@ _setup_arguments() {
# De-initialize if any variables set already.
unset LIST_ACCOUNTS UPDATE_DEFAULT_ACCOUNT CUSTOM_ACCOUNT_NAME NEW_ACCOUNT_NAME DELETE_ACCOUNT_NAME ACCOUNT_ONLY_RUN
unset FOLDERNAME FINAL_LOCAL_INPUT_ARRAY FINAL_ID_INPUT_ARRAY CONTINUE_WITH_NO_INPUT
- unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES SKIP_SUBDIRS ROOTDIR QUIET
+ unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES SKIP_SUBDIRS DESCRIPTION ROOTDIR QUIET
unset VERBOSE VERBOSE_PROGRESS DEBUG LOG_FILE_ID CURL_SPEED RETRY
export CURL_PROGRESS="-s" EXTRA_LOG=":" CURL_PROGRESS_EXTRA="-s"
INFO_PATH="${HOME}/.google-drive-upload" CONFIG_INFO="${INFO_PATH}/google-drive-upload.configpath"
@@ -1615,6 +1633,11 @@ _setup_arguments() {
;;
-o | --overwrite) export OVERWRITE="Overwrite" UPLOAD_MODE="update" ;;
-d | --skip-duplicates) export SKIP_DUPLICATES="Skip Existing" UPLOAD_MODE="update" ;;
+ -desc | --description | --description-all)
+ _check_longoptions "${1}" "${2}"
+ [ "${1}" = "--description-all" ] && export DESCRIPTION_ALL="true"
+ export DESCRIPTION="${2}" && shift
+ ;;
-f | --file | --folder)
_check_longoptions "${1}" "${2}"
LOCAL_INPUT_ARRAY="${LOCAL_INPUT_ARRAY}
@@ -1850,6 +1873,9 @@ _process_arguments() {
esac; do
# Check if the argument is a file or a directory.
if [ -f "${input}" ]; then
+ # export DESCRIPTION_FILE, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": FILE" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_upload_file_main noparse "${input}" "${WORKSPACE_FOLDER_ID}"
@@ -1863,6 +1889,9 @@ _process_arguments() {
input="$(cd "${input}" && pwd)" || return 1 # to handle dirname when current directory (.) is given as input.
unset EMPTY # Used when input folder is empty
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL+:${DESCRIPTION}}"
+
_print_center "justify" "Given Input" ": FOLDER" "-"
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
FOLDER_NAME="${input##*/}" && "${EXTRA_LOG}" "justify" "Folder: ${FOLDER_NAME}" "="
@@ -1993,10 +2022,16 @@ EOF
for _ in 1 2; do _clear_line 1; done
case "${type}" in
*folder*)
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL+:${DESCRIPTION}}"
+
"${QUIET:-_print_center}" "justify" "Folder not supported." "=" 1>&2 && _newline "\n" 1>&2 && continue
## TODO: Add support to clone folders
;;
*)
+ # export DESCRIPTION_FILE, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": File ID" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_clone_file "${UPLOAD_MODE:-create}" "${gdrive_id}" "${WORKSPACE_FOLDER_ID}" "${name}" "${size}" ||
diff --git a/sh/upload.sh b/sh/upload.sh
index 7c1575d..6414a67 100755
--- a/sh/upload.sh
+++ b/sh/upload.sh
@@ -22,6 +22,10 @@ Options:\n
-f | --[file|folder] - Specify files and folders explicitly in one command, use multiple times for multiple folder/files. See README for more use of this command.\n
-cl | --clone - Upload a gdrive file without downloading, require accessible gdrive link or id as argument.\n
-o | --overwrite - Overwrite the files with the same name, if present in the root folder/input folder, also works with recursive folders.\n
+ -desc | --description | --description-all - Specify description for the given file. To use the respective metadata of a file, below is the format:\n
+ File name ( fullname ): %f | Size: %s | Mime Type: %m\n
+ Now to actually use it: --description 'Filename: %f, Size: %s, Mime: %m'\n
+ Note: For files inside folders, use --description-all flag.\n
-d | --skip-duplicates - Do not upload the files with the same name, if already present in the root folder/input folder, also works with recursive folders.\n
-S | --share - Share the uploaded input file/folder, grant reader permission to provided email address or to everyone with the shareable link.\n
--speed 'speed' - Limit the download speed, supported formats: 1K, 1M and 1G.\n
@@ -118,7 +122,7 @@ _setup_arguments() {
# De-initialize if any variables set already.
unset LIST_ACCOUNTS UPDATE_DEFAULT_ACCOUNT CUSTOM_ACCOUNT_NAME NEW_ACCOUNT_NAME DELETE_ACCOUNT_NAME ACCOUNT_ONLY_RUN
unset FOLDERNAME FINAL_LOCAL_INPUT_ARRAY FINAL_ID_INPUT_ARRAY CONTINUE_WITH_NO_INPUT
- unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES SKIP_SUBDIRS ROOTDIR QUIET
+ unset PARALLEL NO_OF_PARALLEL_JOBS SHARE SHARE_EMAIL OVERWRITE SKIP_DUPLICATES SKIP_SUBDIRS DESCRIPTION ROOTDIR QUIET
unset VERBOSE VERBOSE_PROGRESS DEBUG LOG_FILE_ID CURL_SPEED RETRY
export CURL_PROGRESS="-s" EXTRA_LOG=":" CURL_PROGRESS_EXTRA="-s"
INFO_PATH="${HOME}/.google-drive-upload" CONFIG_INFO="${INFO_PATH}/google-drive-upload.configpath"
@@ -201,6 +205,11 @@ _setup_arguments() {
;;
-o | --overwrite) export OVERWRITE="Overwrite" UPLOAD_MODE="update" ;;
-d | --skip-duplicates) export SKIP_DUPLICATES="Skip Existing" UPLOAD_MODE="update" ;;
+ -desc | --description | --description-all)
+ _check_longoptions "${1}" "${2}"
+ [ "${1}" = "--description-all" ] && export DESCRIPTION_ALL="true"
+ export DESCRIPTION="${2}" && shift
+ ;;
-f | --file | --folder)
_check_longoptions "${1}" "${2}"
LOCAL_INPUT_ARRAY="${LOCAL_INPUT_ARRAY}
@@ -436,6 +445,9 @@ _process_arguments() {
esac; do
# Check if the argument is a file or a directory.
if [ -f "${input}" ]; then
+ # export DESCRIPTION_FILE, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": FILE" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_upload_file_main noparse "${input}" "${WORKSPACE_FOLDER_ID}"
@@ -449,6 +461,9 @@ _process_arguments() {
input="$(cd "${input}" && pwd)" || return 1 # to handle dirname when current directory (.) is given as input.
unset EMPTY # Used when input folder is empty
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _upload_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL+:${DESCRIPTION}}"
+
_print_center "justify" "Given Input" ": FOLDER" "-"
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
FOLDER_NAME="${input##*/}" && "${EXTRA_LOG}" "justify" "Folder: ${FOLDER_NAME}" "="
@@ -579,10 +594,16 @@ EOF
for _ in 1 2; do _clear_line 1; done
case "${type}" in
*folder*)
+ # export DESCRIPTION_FILE only if DESCRIPTION_ALL var is available, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION_ALL+:${DESCRIPTION}}"
+
"${QUIET:-_print_center}" "justify" "Folder not supported." "=" 1>&2 && _newline "\n" 1>&2 && continue
## TODO: Add support to clone folders
;;
*)
+ # export DESCRIPTION_FILE, used for descriptions in _clone_file function
+ export DESCRIPTION_FILE="${DESCRIPTION}"
+
_print_center "justify" "Given Input" ": File ID" "="
_print_center "justify" "Upload Method" ": ${SKIP_DUPLICATES:-${OVERWRITE:-Create}}" "=" && _newline "\n"
_clone_file "${UPLOAD_MODE:-create}" "${gdrive_id}" "${WORKSPACE_FOLDER_ID}" "${name}" "${size}" ||