0%

命令行下的share

同学写了个上传文件的网站:share 用于解决linux下QQ传文件的问题。我突发奇想,做一命令行下的share客户端。完整代码见share-terminal

需要用到:

  • zsh
  • xmllint
  • curl
  • wget

首先网站地址是:https://share.whoisnian.com,准备从服务器上拉取文件列表,存在本地/tmp/share.list,下载的时候可以快速补全文件名,创建一个名为share的bash脚本:

url="https://share.whoisnian.com"
localList="/tmp/share.list"

同步列表

首先编写第一个功能,同步远端文件列表到本地:

function _shareSync() {
echo "local file list synchronizing....."
(curl $url | \
xmllint --html --xpath \
'//a[@class="maxlen"]/text()' \
--noout 2>/dev/null - \
) > $localList
echo "Done."
}

这里先用curl获得html代码,然后用管道传输给xmllint,用--xpath解析出class是”maxlen”的链接标签的文本,也就是文件名。用--noout 2>/dev/null取消报错输出,把最终结果也就是文件列表,存入/tmp/share.list
这个临时文件内容是这样:
$ cat /tmp/share.list 
Screenshot_2020-02-05-20-28-47.jpg
beijing_all_20200101.csv
统计学习方法.pdf
trpl-zh-cn.pdf
Wallpaper.jpg
Proxy-SwitchyOmega-Chromium-2.5.15.crx
Shadowsocks-Qt5-3.0.1-x86_64.AppImage
macOSPublicBetaAccessUtility.dmg
jmeter.png
深入浅出React和Redux (实战).pdf
IdeaProjects.rar

下载

下载文件就是按照”https://share.whoisnian.com/upload/"+文件名的链接,直接用`wget`下载

function _shareDownload() {
href=$url"/upload/"$1
echo "href: "$href
wget $href
}

删除

删除文件需要传入POST参数”submit=delete”和”name=文件名”,用curl模拟POST

function _shareDelete() {
echo "delete: "$1
curl -s $url"/index.php" \
-X POST \
-d "name="$1"&submit=delete" \
> /dev/null
_shareSync
}

上传

上传文件,需要传入文件和”submit=upload”参数

function _shareUpload() {
echo "upload: "$1
curl \
-F "file[]=@"$1 \
-F "submit=upload" \
$url"/index.php" > /dev/null
}

命令行参数

最后写做一下提示功能和命令行参数识别:

function help() {
echo "Usage: share [option] <filename>"
echo "Options:"
echo " sync: update local file list from server"
echo " ls: show files from local list"
echo " d: download file"
echo " u: upload local file"
echo " del: delete file from server"
echo "Example:"
echo " share d myfile.txt"
}

if [[ $1 == "sync" ]]; then #synchronize list
_shareSync
elif [[ $1 == "ls" ]]; then #local lost
_shareList
elif [[ $1 == "d" ]]; then #download
if [[ $2 == "" ]]; then
echo "filename required"
else
_shareDownload $2
fi
elif [[ $1 == "u" ]]; then
_shareUpload $2
elif [[ $1 == "del" ]]; then
if [[ $2 == "" ]]; then
echo "filename required"
else
_shareDelete $2
fi
elif [[ $1 == "help" ]]; then
help
elif [[ $1 == "" ]]; then
help
else
echo "unknown option: "$1" sh ,see usage:\"share help\""
fi

自动补全

如果就做到上述的,已经能用了,但是需要手动输入文件名,很麻烦,习惯摁Tab的我当然要实现自动补全。

自动补全需要在shell中配置complete,创建一个bash.rc用于存放自动补全的配置

function _share() {
COMPREPLY=()
local cur=${COMP_WORDS[COMP_CWORD]};
local com=${COMP_WORDS[COMP_CWORD-1]};
case $com in
'share') #如果遇到share命令
COMPREPLY=($(compgen -W 'ls d u help del' -- $cur)) #候选的补全为ls d u help del
;;
'd') #如果第二个参数是d
local pro=($(awk '{print $1}' /tmp/share.list)) #读取临时文件中的文件名,存为数组
COMPREPLY=($(compgen -W "${pro[*]}" -- $cur)) #zsh 从数组中设置候选补全的文件名
#COMPREPLY=($(compgen -W '${pro[@]}' -- $cur)) #bash
;;
*)
;;
esac
return 0
}

complete -F _share share

~/.zshrc中把share加入环境变量$PATH,并source bash.rc就可以了,效果如下:

╭─xuranus@Thanos ~ 
╰─$ share d
beijing_all_20200101.csv macOSPublicBetaAccessUtility.dmg Shadowsocks-Qt5-3.0.1-x86_64.AppImage 深入浅出React和Redux
IdeaProjects.rar Proxy-SwitchyOmega-Chromium-2.5.15.crx trpl-zh-cn.pdf 统计学习方法.pdf
jmeter.png Screenshot_2020-02-05-20-28-47.jpg Wallpaper.jpg

输入share后按Tab可以补全option,如果option是d,则按Tab补全文件名。

需要注意的是:bash和zsh的语法略有差异,根据你的环境需要区别对开。zsh下如果出现command not found:complete,需要在~/.zshrc头加入:

autoload bashcompinit
bashcompinit

最后试试使用效果:

╭─xuranus@Thanos ~ 
╰─$ share sync 130 ↵
local file list synchronizing.....
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 10098 0 10098 0 0 1315 0 --:--:-- 0:00:07 --:--:-- 2237
Done.

╭─xuranus@Thanos ~
╰─$ share ls
Screenshot_2020-02-05-20-28-47.jpg
beijing_all_20200101.csv
统计学习方法.pdf
trpl-zh-cn.pdf
Wallpaper.jpg
Proxy-SwitchyOmega-Chromium-2.5.15.crx
Shadowsocks-Qt5-3.0.1-x86_64.AppImage
macOSPublicBetaAccessUtility.dmg
jmeter.png
IdeaProjects.rar

╭─xuranus@Thanos ~
╰─$ share d 统计学习方法.pdf
href: https://share.whoisnian.com/upload/统计学习方法.pdf
--2020-02-21 10:46:59-- https://share.whoisnian.com/upload/%E7%BB%9F%E8%AE%A1%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95.pdf
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
Resolving share.whoisnian.com (share.whoisnian.com)... 45.77.145.72, 2001:19f0:5:6c2a:5400:2ff:fe1b:7404
Connecting to share.whoisnian.com (share.whoisnian.com)|45.77.145.72|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18415263 (18M) [application/pdf]
Saving to: ‘统计学习方法.pdf’

统计学习方法.pdf 100%[====================================================================================================================>] 17.56M 819KB/s in 49s

2020-02-21 10:47:52 (369 KB/s) - ‘统计学习方法.pdf’ saved [18415263/18415263]

╭─xuranus@Thanos ~/Downloads
╰─$ share u shiyan.json
upload: shiyan.json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 25313 0 10797 100 14516 3591 4829 0:00:03 0:00:03 --:--:-- 8420

╭─xuranus@Thanos ~
╰─$ share del shiyan.json
delete: shiyan.json
local file list synchronizing.....
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 10098 0 10098 0 0 11108 0 --:--:-- --:--:-- --:--:-- 11096
Done.

Disqus评论区没有正常加载,请使用科学上网