(转载)基于Bash命令行的百度云上传下载工具

原文链接:http://hi.baidu.com/meoow/item/aef5814bbd5be3e1bcf451e9

这是我根据百度云PCS的API写的一个基于bash的命令行工具,

使用了curl, awk, sed, xxd, bash,没有使用任何其他的语言解释器做辅助

目前,上传下载,文件列表,文件信息,创建文件夹,删除文件都没问题

复制和移动总是返回参数错误,实在找不出来哪里跟API不一致了,暂时放弃。

另外离线下载相关的API也都添加了,但是因为现在百度云不能申请,我是用的是bypy的client_id,

不知道它的离线下载相关权限没有抑或其他问题,添加任务返回500。

不过总的来说基本上对于一般使用百毒云是够用了

#!/bin/bash

# Baidu Yun Command Line Interface

# Depends: bash, curl, grep, awk, sed, xxd
# (Thay are basicly builtin tools of any *nix system.)
# Additionally, fastupload depends: head, wc, md5sum or md5, cksum
# (Which are also builtin tools)

# issues:
# move, copy and all offline-download related commnads do not work
# the latters are probably prohibited by baidu
# or the current bypy client has no permission for them.

#### Variables ####
# This three to be changed to your own code #
TOKEN=‘00.00000000000000000000000000000000.0000000.0000000000.000000000000000000‘

# 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=‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;‘
########################################

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
    testa-zA-Z0-9.~_-) printf "%s" "$c" ;;
    *) printf "%s" "$c" | xxd -p -c1 | 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
test*\\/^$|‘]‘|‘[‘|‘-‘)
    printf "\\\\%s" "$c"
;;
*)
    printf "%s" "$c"
    esac
done
}

# baidu yun authorize
auth() {
local code
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\}‘)
curl -Ls "https://bypy-tianze.rhcloud.com/auth?code=$code&redirect_uri=oob&"|
grep -o ‘"[^"]\{1,\}":"[^"]\{1,\}"‘|sed -n ‘/access_token/s/^.*:"\([[:xdigit:].-]\{1,\}\)"$/\1/p‘
}

# print help
usage() {
cat <<_EOF_
    $0 <command > [arguments...]
    Command:
    auth
    upload    <FILE > [PATH] [overwrite|newcopy]
    fastupload    <FILE > [PATH] [overwrite|newcopy]
    download  <PATH > [SAVEDIR] [SAVENAME]
    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 test[ "$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)
    }
    print
}
‘
}

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 test[ -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 test[ -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 test[ -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 test[ -z "$1" ];then
    echo "$0 mkdir <PATH > " >&2
    exit 1
fi
path="$1"
;;
meta)
req=GET
method=meta
shift
if test[ -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 test[ -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 test[ -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 test[ -z "$path" || -z "$wd" ];then
    echo "$0 search <PATH > <WORD> " >&2
    exit 1
fi
;;
del|delete)
method=delete
if test[ -z "$1" ];then
    echo "$0 delete <PATH > " >&2
    exit 1
fi
shift
path="$1"
;;
add)
method=add_task
shift
if test[ -z "$1" ];then
    echo "$0 add <LINK > " >&2
    exit 1
fi
link="$1"
shift
path="$1"
;;
query)
method=query_task
shift
if test[ -z "$1" ];then
    echo "$0 query <TASKID > " >&2
    exit 1
fi
taskid="$1"
;;
tasks)
method=list_task
;;
cancel)
method=cancel_task
shift
if test[ -z "$1" ];then
    echo "$0 cancel <TASKID > " >&2
    exit 1
fi
taskid="$1"
;;
trash)
method=listrecycle
;;
restore)
method=restore
shift
if test[ -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‘
;;
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[@]}" -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"
    --data param="{\"list\":[{\"from\":\"$from\",\"to\":\"$to\"}]}"
    -Ls "$uri"
)

;;
*)
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
##########################

使用,假设保存成文件名bdcurl的执行文件:
如果想不用浏览器,而是直接在命令行授权给bypy来使用的话,需要在浏览器里登录 过百毒云,然后在cookie里找到BDUSS(可以用firebug,或者使用sqlite打开浏览器的数据库也能找到),把内容复制到脚本开头的 BDUSS变量里(这个有效期比较长,所以基本只复制一次就可以了,以后token过期后重新认证时可以省略这步),
bdcurl auth
等一小会就会输出token id,把这个段字符串复制到脚本开头的TOKEN变量里,然后就可以使用了。

如果不方便获取BDUSS,就需要把终端输出的网址粘贴到浏览器里获取一个code,然后把code替换
https://bypy-tianze.rhcloud.com/auth?code=$code&redirect_uri=oob&
里面$code的部分,获得最后的access_token放到脚本开始的TOKEN变量里。
然后命令行运行:
bdcurl h 看帮助

bdcurl u file1 down #上传文件到down文件夹
bdcurl f file1 down #快速上传文件(只向服务器查询校验信息,如果百度云上有相同的文件,则直接在建立该文件,不需上传,如果返回error_code,则百毒云上没有相同文件,需要使用bdcurl u上传文件)
bdcurl d down/file1 # 下载指定路径的文件
bdcurl del down/file1 # 删除指定路径的文件
bdcurl l down # 列出 down目录下的所有文件

暂时不支持批量上传下载,毕竟百毒本身没有这样的API,所谓批量得在客户端实现,但是bash来实现相对会麻烦很多,因为没有很好的解析json的方法,如果使用python,perl之类的辅助解析,那就不如干脆直接用python或perl写了。

另外输出结果使用一个compact函数对其做一定程度的简化,其简化程度可通过参数指定,脚本里默认(compact -ftbm, 倒数第四行)使用最大程度简化(如,去除花括号和方括号,去除fs_id,md5校验码,size文件大小,mtime和ctime创建/修改时间 等项目,如果传递参数里去掉-s则会保留size项),可以自行参看脚本里定义compact函数接收参数的说明,选择你合适的输出简化程度

时间: 2024-10-29 19:11:27

(转载)基于Bash命令行的百度云上传下载工具的相关文章

使用cmd命令行方式登录ftp上传下载数据

部分用户在使用ftp工具登录空间上传下载过程中经常会遇到各种问题,如主动模式,被动模式,以及其他导致无法登陆ftp .上传数据.下载数据的问题,这时候不妨使用一下命令行方式.命令行下可以避免很多由于ftp工具配置导致的问题,而且这种方式下下载数据的速率明显比使用ftp工具更快.下面就来看一下如何使用ftp 命令进行简单的上传下载数据.1.登录ftp在“开始”->”运行”中输入“cmd”,进入cmd命令行模式,接下来输入:ftp 118.193.22.151输入自己的网站ip地址,接下来会提示输入

在SecureCRT上,使用命令行从远程服务器上传或者下载文件

引言: 在服务器上,一般都会通过命令行来进行访问.对于上传或者下载文件的需求,除了使用filezilla之类的工具之外,还可以使用rz/sz来完成类似操作. 1.  SecureCRT SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单地说是Windows下登录UNIX或Linux服务器主机的软件. 一般的运维或者开发人员都是使用这些工具来远程登录服务器,完成相应操作. 2.  上传或者下载文件需求 一般服务器如果开发了21端口,并支持ftp协议,则可以使用filezi

windows下命令行终端使用rz上传文件参数详解

rz命令: (X) = option applies to XMODEM only (Y) = option applies to YMODEM only (Z) = option applies to ZMODEM only -+, --append                append to existing files -a, --ascii                 ASCII transfer (change CR/LF to LF) -b, --binary       

百度云上传

http://developer.baidu.com/wiki/index.php?title=docs/pcs http://bce.baidu.com/doc/BOS/index.html http://developer.baidu.com/wiki/index.php?title=docs/cplat/bcs/guidehttp://developer.baidu.com/wiki/index.php?title=docs/cplat/bcs/sdk

基于Java的一个简单的文件上传下载功能

最近在公司给客户端做接口,有一个图片上传和文件下载的功能,本来想用Struts来做文件上传下载,但是看了下公司好像没有这个配置,然后看了下同事的代码,才发现原来Apache也可以简单的实现文件上传下载. 首先引入commons-io-2.2.jar FileUtils为我们提供了很多对文件的操作的方法,比如上传整个文件夹的文件.上传单个文件等 然后请看代码下载: public static void uploadFile(String targetDirectory,String targetF

5个基于Linux命令行的文件下载和网站浏览工具

导读 命令行是GNU/Linux中最神奇迷人的部分,它是非常强大的工具;命令行本身功能多样,多种内建或者第三方的命令行应用使得Linux变得更加健壮和强大.Linux Shell支持多种不同类型的网络应用,无论是BT下载软件,专用下载器或者互联网冲浪. 5个命令行互联网工具 这里我们介绍了5个很好的命令行互联网工具,它们非常有用,也很容易上手. 1. rTorrent rTorrent是基于文本,用C++编写,追求高性能的Torrent客户端.支持大部分标准的Linux发行版,包括FreeBSD

[Android] 基于 Linux 命令行构建 Android 应用(七):自动化构建

本章将演示如何基于 Linux 命令行构建 Android 应用,在开始本章之前,希望你已经阅读之前几章内容. 本文环境为 RHEL Sandiego 32-bits,要基于 Linux CLI 构建 Android 应用,先决环境为: 1. JDK[1] 2. Android SDK 3. Apache Ant 安装过程需要使用 sudo 权限. 1. 搭建环境 1.1. 安装 JDK JDK 是构建 Android 应用先决条件之一,由于版权原因,一般安装 Open JDK. RHEL 中使

bash命令行返回值和展开

bash命令行返回值和展开 bash 命令 状态 返回 1.命令状态结果和执行结果 (1)命令执行的状态返回值,命令执行完成之后,其执行状态结果值保存于bash的特殊状态变量$?中. 0:成功 1-255:失败 [root@yumc66 ~]# date 2016年 12月 20日 星期二 11:57:10 CST [root@yumc66 ~]# echo $? 0 [root@yumc66 ~]# $? -bash: 0: command not found [root@yumc66 ~]#

7个基于Linux命令行的文件下载和网站浏览工具

7个基于Linux命令行的文件下载和网站浏览工具 时间:2015-06-01 09:36来源:linux.cn 编辑:linux.cn 点击: 2282 次 Linux命令行是GNU/Linux中最神奇迷人的部分,它是非常强大的工具.命令行本身功能多样,多种内建或者第三方的命令行应用使得Linux变得更加健壮和强大.Linux Shell支持多种不同类型的网 Linux命令行是GNU/Linux中最神奇迷人的部分,它是非常强大的工具.命令行本身功能多样,多种内建或者第三方的命令行应用使得Linu