-
-
Save huwan/7cbde409afc540a7850a1e968e005918 to your computer and use it in GitHub Desktop.
百度云命令行(bash)上传下载脚本
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Baidu Yun Command Line Interface | |
# Depends: bash, curl, grep, awk, sed, od | |
# (They are basicly builtin tools of any *nix system.) | |
# Additionally, fastupload depends: head, wc, md5sum or md5, cksum | |
# (Which are also builtin tools) | |
#### Variables #### | |
# This three to be changed to your own code # | |
# but using bdcurl.sh auth, the token could be updated by the script itself, | |
# if you have write permission for the resided directory. | |
TOKEN=00.00000000000000000000000000000000.0000000.0000000000.0000000000-0000000 | |
# baidu has prohibited registering new client id | |
# the client_id is borrowed from bypy (Another great baidu yun cli tool written in python) | |
CLIENT_ID=q8WE4EpCsau1oS0MplgMKNBn | |
# you should at least login pan.baidu.com from browser once, | |
# then you can obtain the BDUSS code in the Cookie. | |
BDUSS='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;' | |
######################################## | |
# Note that the root of baidu yun server is located at per app specified path($pathprefix), | |
# not the real root. | |
pathprefix='/apps/bypy/' | |
ACCEPT='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' | |
ACCPET_LANGUAGE='zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3' | |
ACCPET_ENCODING='identity' | |
CACHE_CONTROL='no-cache' | |
CONNECTION='keep-alive' | |
DNT=1 | |
HOST='pcs.baidu.com' | |
ORIGIN='http://pan.baidu.com' | |
PRAGMA='no-cache' | |
REFERER='http://pan.baidu.com/disk/home' | |
UA='Mozilla/5.0 (X11; Linux; rv:5.0) Gecko/5.0 Firefox/5.0' | |
CURL_DEFAULT_ARGS=( | |
-H "Accept: $ACCEPT" | |
-H "Accept-Language: $ACCPET_LANGUAGE" | |
-H "Cache-Control: $CACHE_CONTROL" | |
-H "Connection: $CONNECTION" | |
-H "DNT: $DNT" | |
-H "Host: $HOST" | |
-H "Origin: $ORIGIN" | |
-H "Pragma: $PRAGMA" | |
-H "Referer: $REFERER" | |
-H "Accept-Encoding: $ACCPET_ENCODING" | |
-A "$UA" | |
) | |
#################### | |
#### Defining functions #### | |
# encoding character to %xx format | |
urlencode() { | |
local length="${#1}" | |
local c | |
for (( i = 0; i < length; i++ )); do | |
c="${1:i:1}" | |
case $c in | |
[a-zA-Z0-9.~_-]) printf "%s" "$c" ;; | |
*) printf "%s" "$c" | od -t x1 | | |
awk '{for(i=2;i<=NF;i++)print $i}' | | |
while read x;do printf "%%%s" "$x";done | |
esac | |
done | |
} | |
# for *basic* regexp syntax surrounded by double quotes | |
regexescape() { | |
local len="${#1}" | |
local c | |
for(( i=0;i<len;i++ ));do | |
c="${1:i:1}" | |
case "$c" in | |
[*\\/^$]|']'|'['|'-') | |
printf "\\\\%s" "$c" | |
;; | |
*) | |
printf "%s" "$c" | |
esac | |
done | |
} | |
# baidu yun authorize | |
auth() { | |
local code token | |
printf '\e[1mGetting auth code from:\e[0m\n' | |
echo "http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=$CLIENT_ID&redirect_uri=oob&scope=basic%20netdisk&" | |
code=$(curl -Ls "http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=$CLIENT_ID&redirect_uri=oob&scope=basic%20netdisk&" -H "Cookie: BDUSS=$BDUSS"|grep -o 'readonly value="[^"]*"'|grep -o '[[:xdigit:]]\{32\}') | |
if [[ -z "$code" ]];then | |
echo Failed, exit... | |
exit 1 | |
fi | |
printf 'Auth code is \e[1;31m%s\e[0m\n' "$code" | |
echo | |
printf '\e[1mGetting token from:\e[0m\n' | |
echo "https://bypy-tianze.rhcloud.com/auth?code=$code&redirect_uri=oob&" | |
token=$(curl -3 -Ls "https://bypy-tianze.rhcloud.com/auth?code=$code&redirect_uri=oob&" \ | |
-A 'Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0' \ | |
-H 'Host: bypy-tianze.rhcloud.com'| | |
grep -o '"[^"]\{1,\}":"[^"]\{1,\}"'|sed -n '/access_token/s/^.*:"\([[:xdigit:].-]\{1,\}\)"$/\1/p') | |
if [[ -n "$token" ]];then | |
printf 'Token is \e[1;31m%s\e[0m\n' "$token" | |
echo | |
printf '\e[1mUpdating token in this script...\e[0m\n' | |
local scriptdir=$(dirname "$0") | |
if [[ -w "$scriptdir" ]] && [[ -x "$scriptdir" ]];then | |
sed -i '~' -e "s/^TOKEN=.*$/TOKEN=$token/" "$0" | |
rm "$0~" | |
printf '\e[1mToken updated\e[0m\n' | |
else | |
echo You don\'t have write permission for $0, | |
echo you need to add the token string into this script manually. | |
exit 1 | |
fi | |
fi | |
} | |
# print help | |
usage() { | |
cat <<_EOF_ | |
$0 <command> [arguments...] | |
Command: | |
auth | |
upload <FILE> [PATH] [overwrite|newcopy] | |
fastupload <FILE> [PATH] [overwrite|newcopy] | |
download <PATH> [SAVEDIR] [SAVENAME] | |
downdir <DIR> [SAVEDIR] | |
list [PATH] | |
mkdir <PATH> | |
meta <PATH> | |
move <FROM> <TO> | |
copy <FROM> <TO> | |
delete <PATH> | |
search <PATH> <WORD> | |
add <URI> [PATH] | |
query <TASKID> | |
tasks | |
cancel <TASKID> | |
trash | |
retore <FILEID> | |
_EOF_ | |
} | |
# JSON pretty printer | |
tokenize () { | |
local GREP | |
local ESCAPE | |
local CHAR | |
GREP='egrep -ao' | |
ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})' | |
CHAR='[^[:cntrl:]"\\]' | |
local STRING="\"$CHAR*($ESCAPE$CHAR*)*\"" | |
local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?' | |
local KEYWORD='null|false|true' | |
local SPACE='[[:space:]]+' | |
$GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$" | |
} | |
printw() { | |
local n="$1" | |
if [[ "$n" =~ [1-9][0-9]* ]];then | |
: | |
else | |
return 0 | |
fi | |
for((i=0;i<n;i++));do | |
printf " " | |
done | |
} | |
pprint() { | |
local indent=0 | |
local value=0 | |
while read x; do | |
case "$x" in | |
'{'|'[') | |
if ((value));then | |
printf " " | |
value=0 | |
else | |
printw $indent | |
fi | |
((indent++)) | |
printf "%s\n" "$x" | |
;; | |
'}'|']') | |
value=0 | |
((indent>0 && indent--)) | |
echo | |
printw $indent | |
printf "%s" "$x" | |
;; | |
',') | |
value=0 | |
echo | |
;; | |
':') | |
value=1 | |
printf "%s" "$x" | |
;; | |
*) | |
if ((value));then | |
value=0 | |
printf " " | |
else | |
printw $indent | |
fi | |
printf "%s" "$x" | |
;; | |
esac | |
done | |
} | |
# compact json output (parse output from pprint only) | |
compact() { | |
# arguments: -f -t -b -m -s | |
# -f no fs_id | |
# -t no ctime and mtime | |
# -b no brackets | |
# -m no md5 | |
# -s no size | |
#default is to remove double quotes | |
local sedcmd='s/"\([^"]*\)"/\1/g;' | |
while getopts :ftbms arg;do | |
case "$arg" in | |
f) | |
sedcmd="$sedcmd"'/^ *fs_id/d;' | |
;; | |
t) | |
sedcmd="$sedcmd"'/^ *ctime/d;/^ *mtime/d;' | |
;; | |
m) | |
sedcmd="$sedcmd"'/^ *md5:/d;' | |
;; | |
s) | |
sedcmd="$sedcmd"'/^ *size:/d;' | |
;; | |
b) sedcmd="$sedcmd"'/^ *{/d;s/^ *}$//;/^ *\[$/d;/^ *\]/d;s/: \[$/:/;' | |
;; | |
esac | |
done | |
sed "$sedcmd" | |
} | |
autounit() { | |
awk -v G=$((1024**3)) -v M=$((1024**2)) -v K=1024 ' | |
{ | |
if($0~/^ *"?size"?: [[:digit:]]{1,}/){ | |
if($2>=G){ | |
size=sprintf("%0.1fG",$2/G) | |
} else if($2>=M){ | |
size=sprintf("%0.1fM",$2/M) | |
} else if($2>=K){ | |
size=sprintf("%0.1fK",$2/K) | |
} else { | |
size=$2 | |
} | |
sub($2,size) | |
} | |
} | |
' | |
} | |
crc32() { | |
cksum -o3 < "$1" | | |
while read x y;do | |
echo $x | |
break | |
done | |
} | |
if type -t md5sum >/dev/null ;then | |
MD5='md5sum -b' | |
else | |
MD5='md5' | |
fi | |
md5() { | |
MD5 < "$1" | | |
while read x y;do | |
echo "$x" | |
break | |
done | |
} | |
md5_256k() { | |
head -c262144 "$1" | MD5 | | |
while read x y;do | |
echo "$x" | |
break | |
done | |
} | |
size() { | |
wc -c "$1"| | |
while read x y;do | |
echo "$x" | |
break | |
done | |
} | |
######################################## | |
#### Parse command line arguments #### | |
case "$1" in | |
auth) auth | |
exit 0 | |
;; | |
u|upload) | |
method=upload | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 upload <FILE> [PATH] [overwrite|newcopy]" >&2 | |
exit 1 | |
fi | |
filepath="$1" | |
filename="$(basename "$filepath")" | |
shift | |
path="${1:-/}/$filename" | |
shift | |
ondup="${1:-overwrite}" | |
;; | |
f|fastupload) | |
method=rapidupload | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 upload <FILE> [PATH] [overwrite|newcopy]" >&2 | |
exit 1 | |
fi | |
filepath="$1" | |
filename="$(basename "$filepath")" | |
shift | |
path="${1:-/}/$filename" | |
shift | |
ondup="${1:-overwrite}" | |
;; | |
d|download) | |
method=download | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 download <PATH> [SAVEDIR] [SAVENAME]" >&2 | |
exit 1 | |
fi | |
path="$1" | |
shift | |
savedir="${1:-.}" | |
shift | |
savename="${1:-$(basename "$path")}" | |
savefile="$savedir/$savename" | |
;; | |
mkdir) | |
req=POST | |
method=mkdir | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 mkdir <PATH>" >&2 | |
exit 1 | |
fi | |
path="$1" | |
;; | |
meta) | |
req=GET | |
method=meta | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 meta <PATH>" >&2 | |
exit 1 | |
fi | |
path="$1" | |
;; | |
l|list) | |
method=list | |
shift | |
path="${1:-/}" | |
;; | |
m|move) | |
method=move | |
shift | |
from="$1" | |
shift | |
to="$1" | |
if [[ -z "$from" || -z "$to" ]];then | |
echo "$0 move <FROM> <TO>" >&2 | |
exit 1 | |
fi | |
;; | |
c|copy) | |
method=copy | |
shift | |
from="$1" | |
shift | |
to="$1" | |
if [[ -z "$from" || -z "$to" ]];then | |
echo "$0 copy <FROM> <TO>" >&2 | |
exit 1 | |
fi | |
;; | |
s|search) | |
method=search | |
shift | |
path="$1" | |
shift | |
wd="$1" | |
if [[ -z "$path" || -z "$wd" ]];then | |
echo "$0 search <PATH> <WORD>" >&2 | |
exit 1 | |
fi | |
;; | |
del|delete) | |
method=delete | |
if [[ -z "$1" ]];then | |
echo "$0 delete <PATH>" >&2 | |
exit 1 | |
fi | |
shift | |
path="$1" | |
;; | |
add) | |
method=add_task | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 add <LINK>" >&2 | |
exit 1 | |
fi | |
link="$1" | |
shift | |
path="$1" | |
;; | |
query) | |
method=query_task | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 query <TASKID>" >&2 | |
exit 1 | |
fi | |
taskid="$1" | |
;; | |
tasks) | |
method=list_task | |
;; | |
cancel) | |
method=cancel_task | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 cancel <TASKID>" >&2 | |
exit 1 | |
fi | |
taskid="$1" | |
;; | |
trash) | |
method=listrecycle | |
;; | |
restore) | |
method=restore | |
shift | |
if [[ -z "$1" ]];then | |
echo "$0 restore <FILEID>" >&2 | |
exit 1 | |
fi | |
fsid="$1" | |
;; | |
h|help) | |
usage | |
exit 0 | |
;; | |
*) | |
usage | |
exit 0 | |
;; | |
esac | |
path="$pathprefix""$path" | |
from="$pathprefix""$from" | |
to="$pathprefix""$to" | |
#### determining request type #### | |
case $method in | |
info|download|meta|list|search|generate|diff|streaming|listrecycle) | |
req=GET | |
;; | |
upload|delete|createsuperfile|move|copy|rapidupload|add_task|list_task|query_task|cancel_task|restore|mkdir) | |
req=POST | |
;; | |
esac | |
################################## | |
#### determining URI ############# | |
case $method in | |
upload) uriprefix='https://c.pcs.baidu.com/rest/2.0/pcs/file' | |
;; | |
download) uriprefix='https://d.pcs.baidu.com/rest/2.0/pcs/file' | |
;; | |
add_task|list_task|query_task|cancel_task) | |
uriprefix='https://pcs.baidu.com/rest/2.0/pcs/services/cloud_dl' | |
;; | |
*) uriprefix='https://pcs.baidu.com/rest/2.0/pcs/file' | |
;; | |
esac | |
################################## | |
#### Building URI depends on specific method #### | |
uriprefix="$uriprefix?access_token=$TOKEN&method=$method" | |
case $method in | |
upload) | |
uri="$uriprefix&path=$(urlencode "$path")&ondup=$ondup" | |
;; | |
download|mkdir|meta|delete) | |
uri="$uriprefix&path=$(urlencode "$path")" | |
;; | |
list) | |
by=name #time name size | |
order=asc #asc desc | |
uri="$uriprefix&path=$(urlencode "$path")&by=$by&order=$order" | |
;; | |
move|copy) | |
uri="$uriprefix" | |
;; | |
search) | |
re=1 | |
uri="$uriprefix&path=$(urlencode "$path")&wd=$(urlencode "$wd")&re=$re" | |
;; | |
rapidupload) | |
filelength=$(size "$filepath") | |
filemd5=$(md5 "$filepath") | |
fileslicemd5=$(md5_256k "$filepath") | |
filecrc32=$(crc32 "$filepath") | |
uri="$uriprefix&path=$(urlencode "$path")&content-length=$filelength&content-md5=$filemd5&slice-md5=$fileslicemd5&content-crc32=$filecrc32&ondup=$ondup" | |
;; | |
add_task) | |
uri="$uriprefix&save_path=$(urlencode "$path")&source_url=$(urlencode "$link")" | |
;; | |
query_task) | |
optype=1 | |
uri="$uriprefix&task_ids=$taskid&op_type=$optype" | |
;; | |
list_task) | |
start=0 | |
limit=20 | |
asc=0 #0 1 | |
task_info=1 #1 0 | |
uri="$uriprefix&start=$start&limit=$limit&asc=$asc&need_task_info=$task_info" | |
;; | |
cancel_task) | |
uri="$uriprefix&task_id=$taskid" | |
;; | |
listrecycle) | |
uri="$uriprefix&start=0" | |
;; | |
restore) | |
uri="$uriprefix&fs_id=$fsid" | |
;; | |
esac | |
###################################### | |
## Building arguments for CURL ## | |
curlopts=( | |
-X$req | |
"${CURL_DEFAULT_ARGS[@]}" | |
) | |
case $method in | |
upload) | |
curlopts=("${curlopts[@]}" -F file=@"$filepath" "$uri") | |
;; | |
download) | |
curlopts=("${curlopts[@]}" -L -o "$savefile" "$uri") | |
;; | |
delete|add_task|list_task|query_task|cancel_task|restore|mkdir|rapidupload) | |
curlopts=( | |
"${curlopts[@]}" | |
-H "Content-Length: 0" | |
-Ls "$uri" | |
) | |
;; | |
move|copy) | |
curlopts=( | |
"${curlopts[@]}" | |
#-H "Content-Type: application/json" | |
-H "Content-Length: 0" | |
#--data param="{\"list\":[{\"from\":\"$from\",\"to\":\"$to\"}]}" | |
-Ls "$uri&from=$(urlencode "$from")&to=$(urlencode "$to")" | |
) | |
;; | |
*) | |
curlopts=("${curlopts[@]}" -Ls "$uri") | |
;; | |
esac | |
################################# | |
### Start the operation ### | |
# echo "${curlopts[@]}"; exit | |
case $method in | |
download) | |
curl "${curlopts[@]}" | |
;; | |
*) | |
curl "${curlopts[@]}"| | |
tokenize|pprint| | |
sed '/^ *"path": /s/^\( *"path": "\)'"$(regexescape "$pathprefix")"'\(.*"\)$/\1\2/'| | |
compact -ftbm | autounit | |
;; | |
esac | |
########################### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使用方法
脚本需要预先填写两个用户相关的变量:TOKEN和BDUSS。获取方法如下:
先使用IE登录一遍百度云获取BDUSS:
C:\Users\Atom\AppData\Local\Microsoft\Windows\Temporary Internet Files下cookie:xxxx@baidu.com/的文件,文件第29行即为BDUSS,填写到脚本的BDUSS变量里。(其中xxx为你电脑用户名)
把下面的网址粘贴到浏览器里获取一个code
把code替换下面链接里面yyy的部分,在浏览器中打开,并将获得最后的access_token放到脚本开始的TOKEN变量里。
命令行运行:./bdcurl.sh h 看帮助