A5下载文章资讯

分类分类

编写shell脚本将VPS上的数据备份到Dropbox网盘的方法

2015-07-01 11:09作者:zhao

看到有人用dropbox备份网站数据,所以今天也试了一下,记得以前是一个python脚本,这是用的是bash 脚本,利用dropbox的api来上传下载的,很方便,脚本的地址是Dropbox-Uploader/dropbox_uploader.sh at master · andreafabrizi/Dropbox-Uploader · GitHub ,感谢作者分享这个脚本。

可以到git下载dropbox_uploader.sh,地址为:https://github.com/andreafabrizi/Dropbox-Uploader

或者也可以直接拷贝代码,保存为dropbox_uploader.sh,注意拷贝的时候最好是复制到文本编辑器里面,如notepad++之类的

#!/usr/bin/env bash

#

# Dropbox Uploader

#

# Copyright (C) 2010-2014 Andrea Fabrizi <andrea.fabrizi@gmail.com>

#

# This program is free software; you can redistribute it and/or modify

# it under the terms of the GNU General Public License as published by

# the Free Software Foundation; either version 2 of the License, or

# (at your option) any later version.

#

# This program is distributed in the hope that it will be useful,

# but WITHOUT ANY WARRANTY; without even the implied warranty of

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

# GNU General Public License for more details.

#

# You should have received a copy of the GNU General Public License

# along with this program; if not, write to the Free Software

# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#

#Default configuration file

CONFIG_FILE=~/.dropbox_uploader

#Default chunk size in Mb for the upload process

#It is recommended to increase this value only if you have enough free space on your /tmp partition

#Lower values may increase the number of http requests

CHUNK_SIZE=4

#Curl location

#If not set, curl will be searched into the $PATH

#CURL_BIN="/usr/bin/curl"

#Default values

TMP_DIR="/tmp"

DEBUG=0

QUIET=0

SHOW_PROGRESSBAR=0

SKIP_EXISTING_FILES=0

ERROR_STATUS=0

#Don't edit these...

API_REQUEST_TOKEN_URL="https://api.dropbox.com/1/oauth/request_token"

API_USER_AUTH_URL="https://www2.dropbox.com/1/oauth/authorize"

API_ACCESS_TOKEN_URL="https://api.dropbox.com/1/oauth/access_token"

API_CHUNKED_UPLOAD_URL="https://api-content.dropbox.com/1/chunked_upload"

API_CHUNKED_UPLOAD_COMMIT_URL="https://api-content.dropbox.com/1/commit_chunked_upload"

API_UPLOAD_URL="https://api-content.dropbox.com/1/files_put"

API_DOWNLOAD_URL="https://api-content.dropbox.com/1/files"

API_DELETE_URL="https://api.dropbox.com/1/fileops/delete"

API_MOVE_URL="https://api.dropbox.com/1/fileops/move"

API_COPY_URL="https://api.dropbox.com/1/fileops/copy"

API_METADATA_URL="https://api.dropbox.com/1/metadata"

API_INFO_URL="https://api.dropbox.com/1/account/info"

API_MKDIR_URL="https://api.dropbox.com/1/fileops/create_folder"

API_SHARES_URL="https://api.dropbox.com/1/shares"

APP_CREATE_URL="https://www2.dropbox.com/developers/apps"

RESPONSE_FILE="$TMP_DIR/du_resp_$RANDOM"

CHUNK_FILE="$TMP_DIR/du_chunk_$RANDOM"

TEMP_FILE="$TMP_DIR/du_tmp_$RANDOM"

BIN_DEPS="sed basename date grep stat dd mkdir"

VERSION="0.14"

umask 077

#Check the shell

if [ -z "$BASH_VERSION" ]; then

echo -e "Error: this script requires the BASH shell!"

exit 1

fi

shopt -s nullglob #Bash allows filename patterns which match no files to expand to a null string, rather than themselves

shopt -s dotglob #Bash includes filenames beginning with a "." in the results of filename expansion

#Look for optional config file parameter

while getopts ":qpskdf:" opt; do

case $opt in

f)

CONFIG_FILE=$OPTARG

;;

d)

DEBUG=1

;;

q)

QUIET=1

;;

p)

SHOW_PROGRESSBAR=1

;;

k)

CURL_ACCEPT_CERTIFICATES="-k"

;;

s)

SKIP_EXISTING_FILES=1

;;

?)

echo "Invalid option: -$OPTARG" >&2

exit 1

;;

:)

echo "Option -$OPTARG requires an argument." >&2

exit 1

;;

esac

done

if [[ $DEBUG != 0 ]]; then

echo $VERSION

set -x

RESPONSE_FILE="$TMP_DIR/du_resp_debug"

fi

if [[ $CURL_BIN == "" ]]; then

BIN_DEPS="$BIN_DEPS curl"

CURL_BIN="curl"

fi

#Dependencies check

which $BIN_DEPS > /dev/null

if [[ $? != 0 ]]; then

for i in $BIN_DEPS; do

which $i > /dev/null ||

NOT_FOUND="$i $NOT_FOUND"

done

echo -e "Error: Required program could not be found: $NOT_FOUND"

exit 1

fi

#Check if readlink is installed and supports the -m option

#It's not necessary, so no problem if it's not installed

which readlink > /dev/null

if [[ $? == 0 && $(readlink -m "//test" 2> /dev/null) == "/test" ]]; then

HAVE_READLINK=1

else

HAVE_READLINK=0

fi

#Forcing to use the builtin printf, if it's present, because it's better

#otherwise the external printf program will be used

#Note that the external printf command can cause character encoding issues!

builtin printf "" 2> /dev/null

if [[ $? == 0 ]]; then

PRINTF="builtin printf"

PRINTF_OPT="-v o"

else

PRINTF=$(which printf)

if [[ $? != 0 ]]; then

echo -e "Error: Required program could not be found: printf"

fi

PRINTF_OPT=""

fi

#Print the message based on $QUIET variable

function print

{

if [[ $QUIET == 0 ]]; then

echo -ne "$1";

fi

}

#Returns unix timestamp

function utime

{

echo $(date +%s)

}

#Remove temporary files

function remove_temp_files

{

if [[ $DEBUG == 0 ]]; then

rm -fr "$RESPONSE_FILE"

rm -fr "$CHUNK_FILE"

rm -fr "$TEMP_FILE"

fi
}

#Returns the file size in bytes

# generic GNU Linux: linux-gnu

# windows cygwin: cygwin

# raspberry pi: linux-gnueabihf

# macosx: darwin10.0

# freebsd: FreeBSD

# qnap: linux-gnueabi

# iOS: darwin9

function file_size

{

#Some embedded linux devices

if [[ $OSTYPE == "linux-gnueabi" || $OSTYPE == "linux-gnu" ]]; then

stat -c "%s" "$1"

return

#Generic Unix

elif [[ ${OSTYPE:0:5} == "linux" || $OSTYPE == "cygwin" || ${OSTYPE:0:7} == "solaris" ]]; then

stat --format="%s" "$1"

return

#BSD, OSX and other OSs

else

stat -f "%z" "$1"

return

fi

}

#Usage

function usage

{

echo -e "Dropbox Uploader v$VERSION"

echo -e "Andrea Fabrizi - andrea.fabrizi@gmail.comn"

echo -e "Usage: $0 COMMAND [PARAMETERS]..."

echo -e "nCommands:"

echo -e "t upload <LOCAL_FILE/DIR ...> <REMOTE_FILE/DIR>"

echo -e "t download <REMOTE_FILE/DIR> [LOCAL_FILE/DIR]"

echo -e "t delete <REMOTE_FILE/DIR>"

echo -e "t move <REMOTE_FILE/DIR> <REMOTE_FILE/DIR>"

echo -e "t copy <REMOTE_FILE/DIR> <REMOTE_FILE/DIR>"

echo -e "t mkdir <REMOTE_DIR>"

echo -e "t list [REMOTE_DIR]"

echo -e "t share <REMOTE_FILE>"

echo -e "t info"

echo -e "t unlink"

echo -e "nOptional parameters:"

echo -e "t-f <FILENAME> Load the configuration file from a specific file"

echo -e "t-s Skip already existing files when download/upload. Default: Overwrite"

echo -e "t-d Enable DEBUG mode"

echo -e "t-q Quiet mode. Don't show messages"

echo -e "t-p Show cURL progress meter"

echo -e "t-k Doesn't check for SSL certificates (insecure)"

echo -en "nFor more info and examples, please see the README file.nn"

remove_temp_files

exit 1

}

#Check the curl exit code

function check_http_response

{

CODE=$?

#Checking curl exit code

case $CODE in

#OK

0)

;;

#Proxy error

5)

print "nError: Couldn't resolve proxy. The given proxy host could not be resolved.n"

remove_temp_files

exit 1

;;

#Missing CA certificates

60|58)

print "nError: cURL is not able to performs peer SSL certificate verification.n"

print "Please, install the default ca-certificates bundle.n"

print "To do this in a Debian/Ubuntu based system, try:n"

print " sudo apt-get install ca-certificatesnn"

print "If the problem persists, try to use the -k option (insecure).n"

remove_temp_files

exit 1

;;

6)

print "nError: Couldn't resolve host.n"

remove_temp_files

exit 1

;;

7)

print "nError: Couldn't connect to host.n"

remove_temp_files

exit 1

;;

esac

#Checking response file for generic errors

if grep -q "HTTP/1.1 400" "$RESPONSE_FILE"; then

ERROR_MSG=$(sed -n -e 's/{"error": "([^"]*)"}/1/p' "$RESPONSE_FILE")

case $ERROR_MSG in

*access?attempt?failed?because?this?app?is?not?configured?to?have*)

echo -e "nError: The Permission type/Access level configured doesn't match the DropBox App settings!nPlease run "$0 unlink" and try again."

exit 1

;;

esac

fi

}

#Urlencode

function urlencode

{

local string="${1}"

local strlen=${#string}

local encoded=""

for (( pos=0 ; pos<strlen ; pos++ )); do

c=${string:$pos:1}

case "$c" in

[-_.~a-zA-Z0-9] ) o="${c}" ;;

* ) $PRINTF $PRINTF_OPT '%%%02x' "'$c"

esac

encoded+="${o}"

done

echo "$encoded"

}

function normalize_path

{

path=$(echo -e "$1")

if [[ $HAVE_READLINK == 1 ]]; then

readlink -m "$path"

else

echo "$path"

fi

}

#Check if it's a file or directory

#Returns FILE/DIR/ERR

function db_stat

{

local FILE=$(normalize_path "$1")

#Checking if it's a file or a directory

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_METADATA_URL/$ACCESS_LEVEL/$(urlencode "$FILE")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null

check_http_response

#Even if the file/dir has been deleted from DropBox we receive a 200 OK response

#So we must check if the file exists or if it has been deleted

if grep -q ""is_deleted":" "$RESPONSE_FILE"; then

local IS_DELETED=$(sed -n 's/.*"is_deleted":.([^,]*).*/1/p' "$RESPONSE_FILE")

else

local IS_DELETED="false"

fi

#Exits...

grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"

if [[ $? == 0 && $IS_DELETED != "true" ]]; then

local IS_DIR=$(sed -n 's/^(.*)"contents":.[.*/1/p' "$RESPONSE_FILE")

#It's a directory

if [[ $IS_DIR != "" ]]; then

echo "DIR"

#It's a file

else

echo "FILE"

fi

#Doesn't exists

else

echo "ERR"

fi

}

#Generic upload wrapper around db_upload_file and db_upload_dir functions

#$1 = Local source file/dir

#$2 = Remote destination file/dir

function db_upload

{

local SRC=$(normalize_path "$1")

local DST=$(normalize_path "$2")

#Checking if the file/dir exists

if [[ ! -e $SRC && ! -d $SRC ]]; then

print " > No such file or directory: $SRCn"

ERROR_STATUS=1

return

fi

#Checking if the file/dir has read permissions

if [[ ! -r $SRC ]]; then

print " > Error reading file $SRC: permission deniedn"

ERROR_STATUS=1

return

fi

#Checking if DST it's a folder or if it doesn' exists (in this case will be the destination name)

TYPE=$(db_stat "$DST")

if [[ $TYPE == "DIR" ]]; then

local filename=$(basename "$SRC")

DST="$DST/$filename"

fi

#It's a directory

if [[ -d $SRC ]]; then

db_upload_dir "$SRC" "$DST"

#It's a file

elif [[ -e $SRC ]]; then

db_upload_file "$SRC" "$DST"

#Unsupported object...

else

print " > Skipping not regular file "$SRC"n"

fi

}

#Generic upload wrapper around db_chunked_upload_file and db_simple_upload_file

#The final upload function will be choosen based on the file size

#$1 = Local source file

#$2 = Remote destination file

function db_upload_file

{

local FILE_SRC=$(normalize_path "$1")

local FILE_DST=$(normalize_path "$2")

shopt -s nocasematch

#Checking not allowed file names

basefile_dst=$(basename "$FILE_DST")

if [[ $basefile_dst == "thumbs.db" ||

$basefile_dst == "desktop.ini" ||

$basefile_dst == ".ds_store" ||

$basefile_dst == "iconr" ||

$basefile_dst == ".dropbox" ||

$basefile_dst == ".dropbox.attr"

]]; then

print " > Skipping not allowed file name "$FILE_DST"n"

return

fi

shopt -u nocasematch

#Checking file size

FILE_SIZE=$(file_size "$FILE_SRC")

#Checking if the file already exists

TYPE=$(db_stat "$FILE_DST")

if [[ $TYPE != "ERR" && $SKIP_EXISTING_FILES == 1 ]]; then

print " > Skipping already existing file "$FILE_DST"n"

return

fi

if [[ $FILE_SIZE -gt 157286000 ]]; then

#If the file is greater than 150Mb, the chunked_upload API will be used

db_chunked_upload_file "$FILE_SRC" "$FILE_DST"

else

db_simple_upload_file "$FILE_SRC" "$FILE_DST"

fi

}

#Simple file upload

#$1 = Local source file

#$2 = Remote destination file

function db_simple_upload_file

{

local FILE_SRC=$(normalize_path "$1")

local FILE_DST=$(normalize_path "$2")

if [[ $SHOW_PROGRESSBAR == 1 && $QUIET == 0 ]]; then

CURL_PARAMETERS="--progress-bar"

LINE_CR="n"

else

CURL_PARAMETERS="-s"

LINE_CR=""

fi

print " > Uploading "$FILE_SRC" to "$FILE_DST"... $LINE_CR"

$CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS -i --globoff -o "$RESPONSE_FILE" --upload-file "$FILE_SRC" "$API_UPLOAD_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM"

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "DONEn"

else

print "FAILEDn"

print "An error occurred requesting /uploadn"

ERROR_STATUS=1

fi

}

#Chunked file upload

#$1 = Local source file

#$2 = Remote destination file

function db_chunked_upload_file

{

local FILE_SRC=$(normalize_path "$1")

local FILE_DST=$(normalize_path "$2")

print " > Uploading "$FILE_SRC" to "$FILE_DST""

local FILE_SIZE=$(file_size "$FILE_SRC")

local OFFSET=0

local UPLOAD_ID=""

local UPLOAD_ERROR=0

local CHUNK_PARAMS=""

#Uploading chunks...

while ([[ $OFFSET != $FILE_SIZE ]]); do

let OFFSET_MB=$OFFSET/1024/1024

#Create the chunk

dd if="$FILE_SRC" of="$CHUNK_FILE" bs=1048576 skip=$OFFSET_MB count=$CHUNK_SIZE 2> /dev/null

#Only for the first request these parameters are not included

if [[ $OFFSET != 0 ]]; then

CHUNK_PARAMS="upload_id=$UPLOAD_ID&offset=$OFFSET"

fi

#Uploading the chunk...

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --upload-file "$CHUNK_FILE" "$API_CHUNKED_UPLOAD_URL?$CHUNK_PARAMS&oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "."

UPLOAD_ERROR=0

UPLOAD_ID=$(sed -n 's/.*"upload_id": *"*([^"]*)"*.*/1/p' "$RESPONSE_FILE")

OFFSET=$(sed -n 's/.*"offset": *([^}]*).*/1/p' "$RESPONSE_FILE")

else

print "*"

let UPLOAD_ERROR=$UPLOAD_ERROR+1

#On error, the upload is retried for max 3 times

if [[ $UPLOAD_ERROR -gt 2 ]]; then

print " FAILEDn"

print "An error occurred requesting /chunked_uploadn"

ERROR_STATUS=1

return

fi

fi

done

UPLOAD_ERROR=0

#Commit the upload

while (true); do

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "upload_id=$UPLOAD_ID&oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_CHUNKED_UPLOAD_COMMIT_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "."

UPLOAD_ERROR=0

break

else

print "*"

let UPLOAD_ERROR=$UPLOAD_ERROR+1

#On error, the commit is retried for max 3 times

if [[ $UPLOAD_ERROR -gt 2 ]]; then

print " FAILEDn"

print "An error occurred requesting /commit_chunked_uploadn"

ERROR_STATUS=1

return

fi

fi

done

print " DONEn"

}

#Directory upload

#$1 = Local source dir

#$2 = Remote destination dir

function db_upload_dir

{

local DIR_SRC=$(normalize_path "$1")

local DIR_DST=$(normalize_path "$2")

#Creatig remote directory

db_mkdir "$DIR_DST"

for file in "$DIR_SRC/"*; do

db_upload "$file" "$DIR_DST"

done

}

#Returns the free space on DropBox in bytes

function db_free_quota

{

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_INFO_URL" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

quota=$(sed -n 's/.*"quota": ([0-9]*).*/1/p' "$RESPONSE_FILE")

used=$(sed -n 's/.*"normal": ([0-9]*).*/1/p' "$RESPONSE_FILE")

let free_quota=$quota-$used

echo $free_quota

else

echo 0

fi

}

#Generic download wrapper

#$1 = Remote source file/dir

#$2 = Local destination file/dir

function db_download

{

local SRC=$(normalize_path "$1")

local DST=$(normalize_path "$2")

TYPE=$(db_stat "$SRC")

#It's a directory

if [[ $TYPE == "DIR" ]]; then

#If the DST folder is not specified, I assume that is the current directory

if [[ $DST == "" ]]; then

DST="."

fi

#Checking if the destination directory exists

if [[ ! -d $DST ]]; then

local basedir=""

else

local basedir=$(basename "$SRC")

fi

local DEST_DIR=$(normalize_path "$DST/$basedir")

print " > Downloading "$SRC" to "$DEST_DIR"... n"

print " > Creating local directory "$DEST_DIR"... "

mkdir -p "$DEST_DIR"

#Check

if [[ $? == 0 ]]; then

print "DONEn"

else

print "FAILEDn"

ERROR_STATUS=1

return

fi

#Extracting directory content [...]

#and replacing "}, {" with "}n{"

#I don't like this piece of code... but seems to be the only way to do this with SED, writing a portable code...

local DIR_CONTENT=$(sed -n 's/.*: [{(.*)/1/p' "$RESPONSE_FILE" | sed 's/}, *{/}

{/g')

#Extracting files and subfolders

TMP_DIR_CONTENT_FILE="${RESPONSE_FILE}_$RANDOM"

echo "$DIR_CONTENT" | sed -n 's/.*"path": *"([^"]*)",.*"is_dir": *([^"]*),.*/1:2/p' > $TMP_DIR_CONTENT_FILE

#For each entry...

while read -r line; do

local FILE=${line%:*}

local TYPE=${line#*:}

#Removing unneeded /

FILE=${FILE##*/}

if [[ $TYPE == "false" ]]; then

db_download_file "$SRC/$FILE" "$DEST_DIR/$FILE"

else

db_download "$SRC/$FILE" "$DEST_DIR"

fi

done < $TMP_DIR_CONTENT_FILE

rm -fr $TMP_DIR_CONTENT_FILE

#It's a file

elif [[ $TYPE == "FILE" ]]; then

#Checking DST

if [[ $DST == "" ]]; then

DST=$(basename "$SRC")

fi

#If the destination is a directory, the file will be download into

if [[ -d $DST ]]; then

DST="$DST/$SRC"

fi

db_download_file "$SRC" "$DST"

#Doesn't exists

else

print " > No such file or directory: $SRCn"

ERROR_STATUS=1

return

fi

}

#Simple file download

#$1 = Remote source file

#$2 = Local destination file

function db_download_file

{

local FILE_SRC=$(normalize_path "$1")

local FILE_DST=$(normalize_path "$2")

if [[ $SHOW_PROGRESSBAR == 1 && $QUIET == 0 ]]; then

CURL_PARAMETERS="--progress-bar"

LINE_CR="n"

else

CURL_PARAMETERS="-s"

LINE_CR=""

fi

#Checking if the file already exists

if [[ -e $FILE_DST && $SKIP_EXISTING_FILES == 1 ]]; then

print " > Skipping already existing file "$FILE_DST"n"

return

fi

#Creating the empty file, that for two reasons:

#1) In this way I can check if the destination file is writable or not

#2) Curl doesn't automatically creates files with 0 bytes size

dd if=/dev/zero of="$FILE_DST" count=0 2> /dev/null

if [[ $? != 0 ]]; then

print " > Error writing file $FILE_DST: permission deniedn"

ERROR_STATUS=1

return

fi

print " > Downloading "$FILE_SRC" to "$FILE_DST"... $LINE_CR"

$CURL_BIN $CURL_ACCEPT_CERTIFICATES $CURL_PARAMETERS --globoff -D "$RESPONSE_FILE" -o "$FILE_DST" "$API_DOWNLOAD_URL/$ACCESS_LEVEL/$(urlencode "$FILE_SRC")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM"

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "DONEn"

else

print "FAILEDn"

rm -fr "$FILE_DST"

ERROR_STATUS=1

return

fi

}

#Prints account info

function db_account_info

{

print "Dropbox Uploader v$VERSIONnn"

print " > Getting info... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_INFO_URL" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

name=$(sed -n 's/.*"display_name": "([^"]*).*/1/p' "$RESPONSE_FILE")

echo -e "nnName:t$name"

uid=$(sed -n 's/.*"uid": ([0-9]*).*/1/p' "$RESPONSE_FILE")

echo -e "UID:t$uid"

email=$(sed -n 's/.*"email": "([^"]*).*/1/p' "$RESPONSE_FILE")

echo -e "Email:t$email"

quota=$(sed -n 's/.*"quota": ([0-9]*).*/1/p' "$RESPONSE_FILE")

let quota_mb=$quota/1024/1024

echo -e "Quota:t$quota_mb Mb"

used=$(sed -n 's/.*"normal": ([0-9]*).*/1/p' "$RESPONSE_FILE")

let used_mb=$used/1024/1024

echo -e "Used:t$used_mb Mb"

let free_mb=($quota-$used)/1024/1024

echo -e "Free:t$free_mb Mb"

echo ""

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

#Account unlink

function db_unlink

{

echo -ne "Are you sure you want unlink this script from your Dropbox account? [y/n]"

read answer

if [[ $answer == "y" ]]; then

rm -fr "$CONFIG_FILE"

echo -ne "DONEn"

fi

}

#Delete a remote file

#$1 = Remote file to delete

function db_delete

{

local FILE_DST=$(normalize_path "$1")

print " > Deleting "$FILE_DST"... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&path=$(urlencode "$FILE_DST")" "$API_DELETE_URL" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "DONEn"

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

#Move/Rename a remote file

#$1 = Remote file to rename or move

#$2 = New file name or location

function db_move

{

local FILE_SRC=$(normalize_path "$1")

local FILE_DST=$(normalize_path "$2")

TYPE=$(db_stat "$FILE_DST")

#If the destination it's a directory, the source will be moved into it

if [[ $TYPE == "DIR" ]]; then

local filename=$(basename "$FILE_SRC")

FILE_DST=$(normalize_path "$FILE_DST/$filename")

fi

print " > Moving "$FILE_SRC" to "$FILE_DST" ... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&from_path=$(urlencode "$FILE_SRC")&to_path=$(urlencode "$FILE_DST")" "$API_MOVE_URL" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "DONEn"

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

#Copy a remote file to a remote location

#$1 = Remote file to rename or move

#$2 = New file name or location

function db_copy

{

local FILE_SRC=$(normalize_path "$1")

local FILE_DST=$(normalize_path "$2")

TYPE=$(db_stat "$FILE_DST")

#If the destination it's a directory, the source will be copied into it

if [[ $TYPE == "DIR" ]]; then

local filename=$(basename "$FILE_SRC")

FILE_DST=$(normalize_path "$FILE_DST/$filename")

fi

print " > Copying "$FILE_SRC" to "$FILE_DST" ... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&from_path=$(urlencode "$FILE_SRC")&to_path=$(urlencode "$FILE_DST")" "$API_COPY_URL" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "DONEn"

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

#Create a new directory

#$1 = Remote directory to create

function db_mkdir

{

local DIR_DST=$(normalize_path "$1")

print " > Creating Directory "$DIR_DST"... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&root=$ACCESS_LEVEL&path=$(urlencode "$DIR_DST")" "$API_MKDIR_URL" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print "DONEn"

elif grep -q "^HTTP/1.1 403 Forbidden" "$RESPONSE_FILE"; then

print "ALREADY EXISTSn"

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

#List remote directory

#$1 = Remote directory

function db_list

{

local DIR_DST=$(normalize_path "$1")

print " > Listing "$DIR_DST"... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_METADATA_URL/$ACCESS_LEVEL/$(urlencode "$DIR_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

local IS_DIR=$(sed -n 's/^(.*)"contents":.[.*/1/p' "$RESPONSE_FILE")

#It's a directory

if [[ $IS_DIR != "" ]]; then

print "DONEn"

#Extracting directory content [...]

#and replacing "}, {" with "}n{"

#I don't like this piece of code... but seems to be the only way to do this with SED, writing a portable code...

local DIR_CONTENT=$(sed -n 's/.*: [{(.*)/1/p' "$RESPONSE_FILE" | sed 's/}, *{/}

{/g')

#Converting escaped quotes to unicode format

echo "$DIR_CONTENT" | sed 's/"/u0022/' > "$TEMP_FILE"

#Extracting files and subfolders

rm -fr "$RESPONSE_FILE"

while read -r line; do

local FILE=$(echo "$line" | sed -n 's/.*"path": *"([^"]*)".*/1/p')

local IS_DIR=$(echo "$line" | sed -n 's/.*"is_dir": *([^,]*).*/1/p')

local SIZE=$(echo "$line" | sed -n 's/.*"bytes": *([0-9]*).*/1/p')

echo -e "$FILE:$IS_DIR;$SIZE" >> "$RESPONSE_FILE"

done < "$TEMP_FILE"

#Looking for the biggest file size

#to calculate the padding to use

local padding=0

while read -r line; do

local FILE=${line%:*}

local META=${line##*:}

local SIZE=${META#*;}

if [[ ${#SIZE} -gt $padding ]]; then

padding=${#SIZE}

fi

done < "$RESPONSE_FILE"

#For each entry, printing directories...

while read -r line; do

local FILE=${line%:*}

local META=${line##*:}

local TYPE=${META%;*}

local SIZE=${META#*;}

#Removing unneeded /

FILE=${FILE##*/}

if [[ $TYPE != "false" ]]; then

FILE=$(echo -e "$FILE")

$PRINTF " [D] %-${padding}s %sn" "$SIZE" "$FILE"

fi

done < "$RESPONSE_FILE"

#For each entry, printing files...

while read -r line; do

local FILE=${line%:*}

local META=${line##*:}

local TYPE=${META%;*}

local SIZE=${META#*;}

#Removing unneeded /

FILE=${FILE##*/}

if [[ $TYPE == "false" ]]; then

FILE=$(echo -e "$FILE")

$PRINTF " [F] %-${padding}s %sn" "$SIZE" "$FILE"

fi

done < "$RESPONSE_FILE"

#It's a file

else

print "FAILED: $DIR_DST is not a directory!n"

ERROR_STATUS=1

fi

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

#Share remote file

#$1 = Remote file

function db_share

{

local FILE_DST=$(normalize_path "$1")

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" "$API_SHARES_URL/$ACCESS_LEVEL/$(urlencode "$FILE_DST")?oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_ACCESS_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_ACCESS_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM&short_url=false" 2> /dev/null

check_http_response

#Check

if grep -q "^HTTP/1.1 200 OK" "$RESPONSE_FILE"; then

print " > Share link: "

echo $(sed -n 's/.*"url": "([^"]*).*/1/p' "$RESPONSE_FILE")

else

print "FAILEDn"

ERROR_STATUS=1

fi

}

################

#### SETUP ####

################

#CHECKING FOR AUTH FILE

if [[ -e $CONFIG_FILE ]]; then

#Loading data... and change old format config if necesary.

source "$CONFIG_FILE" 2>/dev/null || {

sed -i'' 's/:/=/' "$CONFIG_FILE" && source "$CONFIG_FILE" 2>/dev/null

}

#Checking the loaded data

if [[ $APPKEY == "" || $APPSECRET == "" || $OAUTH_ACCESS_TOKEN_SECRET == "" || $OAUTH_ACCESS_TOKEN == "" ]]; then

echo -ne "Error loading data from $CONFIG_FILE...n"

echo -ne "It is recommended to run $0 unlinkn"

remove_temp_files

exit 1

fi

#Back compatibility with previous Dropbox Uploader versions

if [[ $ACCESS_LEVEL == "" ]]; then

ACCESS_LEVEL="dropbox"

fi

#NEW SETUP...

else

echo -ne "n This is the first time you run this script.nn"

echo -ne " 1) Open the following URL in your Browser, and log in using your account: $APP_CREATE_URLn"

echo -ne " 2) Click on "Create App", then select "Dropbox API app"n"

echo -ne " 3) Select "Files and datastores"n"

echo -ne " 4) Now go on with the configuration, choosing the app permissions and access restrictions to your DropBox foldern"

echo -ne " 5) Enter the "App Name" that you prefer (e.g. MyUploader$RANDOM$RANDOM$RANDOM)nn"

echo -ne " Now, click on the "Create App" button.nn"

echo -ne " When your new App is successfully created, please type then"

echo -ne " App Key, App Secret and the Permission type shown in the confirmation page:nn"

#Getting the app key and secret from the user

while (true); do

echo -n " # App key: "

read APPKEY

echo -n " # App secret: "

read APPSECRET

echo -n " # Permission type, App folder or Full Dropbox [a/f]: "

read ACCESS_LEVEL

if [[ $ACCESS_LEVEL == "a" ]]; then

ACCESS_LEVEL="sandbox"

ACCESS_MSG="App Folder"

else

ACCESS_LEVEL="dropbox"

ACCESS_MSG="Full Dropbox"

fi

echo -ne "n > App key is $APPKEY, App secret is $APPSECRET and Access level is $ACCESS_MSG. Looks ok? [y/n]: "

read answer

if [[ $answer == "y" ]]; then

break;

fi

done

#TOKEN REQUESTS

echo -ne "n > Token request... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_REQUEST_TOKEN_URL" 2> /dev/null

check_http_response

OAUTH_TOKEN_SECRET=$(sed -n 's/oauth_token_secret=([a-z A-Z 0-9]*).*/1/p' "$RESPONSE_FILE")

OAUTH_TOKEN=$(sed -n 's/.*oauth_token=([a-z A-Z 0-9]*)/1/p' "$RESPONSE_FILE")

if [[ $OAUTH_TOKEN != "" && $OAUTH_TOKEN_SECRET != "" ]]; then

echo -ne "OKn"

else

echo -ne " FAILEDnn Please, check your App key and secret...nn"

remove_temp_files

exit 1

fi

while (true); do

#USER AUTH

echo -ne "n Please open the following URL in your browser, and allow Dropbox Uploadern"

echo -ne " to access your DropBox folder:nn --> ${API_USER_AUTH_URL}?oauth_token=$OAUTH_TOKENn"

echo -ne "nPress enter when done...n"

read

#API_ACCESS_TOKEN_URL

echo -ne " > Access Token request... "

$CURL_BIN $CURL_ACCEPT_CERTIFICATES -s --show-error --globoff -i -o "$RESPONSE_FILE" --data "oauth_consumer_key=$APPKEY&oauth_token=$OAUTH_TOKEN&oauth_signature_method=PLAINTEXT&oauth_signature=$APPSECRET%26$OAUTH_TOKEN_SECRET&oauth_timestamp=$(utime)&oauth_nonce=$RANDOM" "$API_ACCESS_TOKEN_URL" 2> /dev/null

check_http_response

OAUTH_ACCESS_TOKEN_SECRET=$(sed -n 's/oauth_token_secret=([a-z A-Z 0-9]*)&.*/1/p' "$RESPONSE_FILE")

OAUTH_ACCESS_TOKEN=$(sed -n 's/.*oauth_token=([a-z A-Z 0-9]*)&.*/1/p' "$RESPONSE_FILE")

OAUTH_ACCESS_UID=$(sed -n 's/.*uid=([0-9]*)/1/p' "$RESPONSE_FILE")

if [[ $OAUTH_ACCESS_TOKEN != "" && $OAUTH_ACCESS_TOKEN_SECRET != "" && $OAUTH_ACCESS_UID != "" ]]; then

echo -ne "OKn"

#Saving data in new format, compatible with source command.

echo "APPKEY=$APPKEY" > "$CONFIG_FILE"

echo "APPSECRET=$APPSECRET" >> "$CONFIG_FILE"

echo "ACCESS_LEVEL=$ACCESS_LEVEL" >> "$CONFIG_FILE"

echo "OAUTH_ACCESS_TOKEN=$OAUTH_ACCESS_TOKEN" >> "$CONFIG_FILE"

echo "OAUTH_ACCESS_TOKEN_SECRET=$OAUTH_ACCESS_TOKEN_SECRET" >> "$CONFIG_FILE"

echo -ne "n Setup completed!n"

break

else

print " FAILEDn"

ERROR_STATUS=1

fi

done;

remove_temp_files

exit $ERROR_STATUS

fi

################

#### START ####

################

COMMAND=${@:$OPTIND:1}

ARG1=${@:$OPTIND+1:1}

ARG2=${@:$OPTIND+2:1}

let argnum=$#-$OPTIND

#CHECKING PARAMS VALUES

case $COMMAND in

upload)

if [[ $argnum -lt 2 ]]; then

usage

fi

FILE_DST=${@:$#:1}

for (( i=$OPTIND+1; i<$#; i++ )); do

FILE_SRC=${@:$i:1}

db_upload "$FILE_SRC" "/$FILE_DST"

done

;;

download)

if [[ $argnum -lt 1 ]]; then

usage

fi

FILE_SRC=$ARG1

FILE_DST=$ARG2

db_download "/$FILE_SRC" "$FILE_DST"

;;

share)

if [[ $argnum -lt 1 ]]; then

usage

fi

FILE_DST=$ARG1

db_share "/$FILE_DST"

;;

info)

db_account_info

;;

delete|remove)

if [[ $argnum -lt 1 ]]; then

usage

fi

FILE_DST=$ARG1

db_delete "/$FILE_DST"

;;

move|rename)

if [[ $argnum -lt 2 ]]; then

usage

fi

FILE_SRC=$ARG1

FILE_DST=$ARG2

db_move "/$FILE_SRC" "/$FILE_DST"

;;

copy)

if [[ $argnum -lt 2 ]]; then

usage

fi

FILE_SRC=$ARG1

FILE_DST=$ARG2

db_copy "/$FILE_SRC" "/$FILE_DST"

;;

mkdir)

if [[ $argnum -lt 1 ]]; then

usage

fi

DIR_DST=$ARG1

db_mkdir "/$DIR_DST"

;;

list)

DIR_DST=$ARG1

#Checking DIR_DST

if [[ $DIR_DST == "" ]]; then

DIR_DST="/"

fi

db_list "/$DIR_DST"

;;

unlink)

db_unlink

;;

*)

if [[ $COMMAND != "" ]]; then

print "Error: Unknown command: $COMMANDnn"

ERROR_STATUS=1

fi

usage

;;

esac

remove_temp_files

exit $ERROR_STATUS

第一次使用,这个脚本会给你指导,告诉你去哪里获得dropbox的 API key 。

因为只有配置好了 API key ,这样才能授权给脚本应用进入你的dropbox目录

 

展开全部

相关

说两句网友评论
    我要跟贴
    取消