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}" ||