curl命令行上传文件并指定mime

用curl下载网页估计大家都会,但是模拟 multipart/form-data 形式的 form 上传文件则稍稍复杂些。命令行如下。

curl -F "action=upload" -F "filename=@file.tar.gz" http://localhost/action.php

如果使用了-F参数,curl就会以 multipart/form-data 的方式发送POST请求。-F参数以name=value的方式来指定参数内容,如果值是一个文件,则需要以name=@file的方式来指定。

如果通过代理,上面的命令有可能会被代理拒绝,这时需要指定上传文件的MIME类型。

curl -x myproxy.com:1080 -F "action=upload" -F "filename=@file.tar.gz;type=application/octet-stream" http://localhost/action.php

 

svn diff 命令行输出格式详解

main.c文件的内容如下

  1 #include <stdio.h>
  2 #include "add.h"
  3 #include "sub.h"
  4
  5 int main()
  6 {
  7         printf("5 + 10 = %d.n",add(5,10));
  8         printf("15 - 10 = %d.n",sub(15,10));
  9         //kris's test
 10         printf("kris: 12 + 28 = %d.n",add(12,28));
 11         //sally's test
 12         printf("sally: 60 - 33 = %d.n",sub(60,33));
 13         return 0;
 14 }

下面,我们做一些修改,具体如下

  1 #include <stdio.h>
  2 #include "add.h"
  3 #include "sub.h"
  4
  5 int main()
  6 {
  7         printf("5 + 10 = %d.n",add(5,10));
  8         printf("15 - 10 = %d.n",sub(15,10));
  9         //kris's test
 10         printf("kris: 32 + 28 = %d.n",add(32,28));
 11         printf("kris: 15 - 10 = %d.n",sub(15,10));
 12         //sally's test
 13         printf("sally: 60 - 33 = %d.n",sub(60,33));
 14         return 0;
 15 }

修改完后,调用svn diff命令,会有如下的输出,下面就说说输出中各部分的意思。

root@letuknowit:/home/kris/calc/trunk# svn diff main.c
Index: main.c
===================================================================
--- main.c      (revision 8)
+++ main.c      (working copy)
@@ -7,7 +7,8 @@
        printf("5 + 10 = %d.n",add(5,10));
        printf("15 - 10 = %d.n",sub(15,10));
        //kris's test
-       printf("kris: 12 + 28 = %d.n",add(12,28));
+       printf("kris: 32 + 28 = %d.n",add(32,28));
+       printf("kris: 15 - 10 = %d.n",sub(15,10));
        //sally's test
        printf("sally: 60 - 33 = %d.n",sub(60,33));
        return 0;

Index: main.c

svn diff可以查看当前工作拷贝中所有的被修改的文件,对于每个文件的diff输出部分由Index: 文件名的形式进行区分。
等于号后面的内容就是关于main.c文件的diff情况了。

--- main.c      (revision 8)
+++ main.c      (working copy)

— 打头的是原始文件,也就是版本库中的最新版本,或者理解为修改前的文件
+++ 打头的是目标文件,这个就是你修改后的版本

@@ -7,7 +7,8 @@

这里的-和+分别表示原始文件和目标文件,7,7表示从第7行开始的7行,-7,7就是原始文件的从第7行开始的7行内容,+7,8的意思类似,表示目标文件从第7行开始的8行内容。结合起来理解就是:
目标文件从第7行开始的8行内容和原始文件的从第7行开始的7行内容之间存在差异

        printf("5 + 10 = %d.n",add(5,10));
        printf("15 - 10 = %d.n",sub(15,10));
        //kris's test
-       printf("kris: 12 + 28 = %d.n",add(12,28));
+       printf("kris: 32 + 28 = %d.n",add(32,28));
+       printf("kris: 15 - 10 = %d.n",sub(15,10));
        //sally's test
        printf("sally: 60 - 33 = %d.n",sub(60,33));
        return 0;

这个就是具体的差异情况了,前面的-号表示需要从原始文件中删除的行,+号表示目标文件中将要增加的行,-号开头的部分只属于原始文件,+号开头的部分只属于目标文件,其余的是两者相同的部分。

  7   1   1         printf("5 + 10 = %d.n",add(5,10));
  8   2   2         printf("15 - 10 = %d.n",sub(15,10));
  9   3   3         //kris's test
 10   4     -       printf("kris: 12 + 28 = %d.n",add(12,28));
 11       4 +       printf("kris: 32 + 28 = %d.n",add(32,28));
 12       5 +       printf("kris: 15 - 10 = %d.n",sub(15,10));
 13   5   6         //sally's test
 14   6   7         printf("sally: 60 - 33 = %d.n",sub(60,33));
 15   7   8         return 0;

为了进一步了解@@ -7,7 +7,8 @@的意思,上面加上了行号等信息,第一列的数字是行号,后面两列的数字表示第几行。经过标注可以清晰的看出原始文件第7行开始的7行和目标文件第7行开始的8行内容了。

参考
http://www.letuknowit.com/archives/avn-diff-output-interpreter



Bash比较版本号

Linux下bash直接用sort -V实现,Mac下的bash没有-V选项,研究之后有两种方式可以实现,第一种纯sort命令方式,第二种自行写逻辑。

第一种:

sort -n -t . -k 1,3 version.txt

结果:

1.01.2
1.1.0
1.12.3
1.2.5
2.4

第二种,来自(stackoverflow)

#!/bin/bash
vercomp () {
    if [[ $1 == $2 ]]
    then
        return 0
    fi
    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

testvercomp () {
    vercomp $1 $2
    case $? in
        0) op='=';;
        1) op='>';;
        2) op='<';;
    esac
    if [[ $op != $3 ]]
    then
        echo "FAIL: Expected '$3', Actual '$op', Arg1 '$1', Arg2 '$2'"
    else
        echo "Pass: '$1 $op $2'"
    fi
}

# Run tests
# argument table format:
# testarg1   testarg2     expected_relationship
echo "The following tests should pass"
while read -r test
do
    testvercomp $test
done << EOF
1            1            =
2.1          2.2          <
3.0.4.10     3.0.4.2      >
4.08         4.08.01      <
3.2.1.9.8144 3.2          >
3.2          3.2.1.9.8144 <
1.2          2.1          <
2.1          1.2          >
5.6.7        5.6.7        =
1.01.1       1.1.1        =
1.1.1        1.01.1       =
1            1.0          =
1.0          1            =
1.0.2.0      1.0.2        =
1..0         1.0          =
1.0          1..0         =
EOF

echo "The following test should fail (test the tester)"
testvercomp 1 1 '>'
$ . ./vercomp
The following tests should pass
Pass: '1 = 1'
Pass: '2.1 < 2.2'
Pass: '3.0.4.10 > 3.0.4.2'
Pass: '4.08 < 4.08.01'
Pass: '3.2.1.9.8144 > 3.2'
Pass: '3.2 < 3.2.1.9.8144'
Pass: '1.2 < 2.1'
Pass: '2.1 > 1.2'
Pass: '5.6.7 = 5.6.7'
Pass: '1.01.1 = 1.1.1'
Pass: '1.1.1 = 1.01.1'
Pass: '1 = 1.0'
Pass: '1.0 = 1'
Pass: '1.0.2.0 = 1.0.2'
Pass: '1..0 = 1.0'
Pass: '1.0 = 1..0'
The following test should fail (test the tester)
FAIL: Expected '>', Actual '=', Arg1 '1', Arg2 '1'

参考:

http://stackoverflow.com/questions/4023830/how-compare-two-strings-in-dot-separated-version-format-in-bash

Mac rsync+fswatch(inotify) 全自动同步

原创脚本,在bash下通用,mac下是fswatch(从brew安装),linux换成inotifywait即可,脚本写到这水平真不是一般的NB。
用法:

  1. 脚本参数和fswatch参数一致。
  2. fswatch默认忽略了.git .svn和IDE的meta文件,需要忽略其他自行添加即可(可写死可传递命令行参数)。
  3. 在脚本内部也可以设置全局忽略,见$excludeCommon变量,针对单个项目设置忽略见exclude[0]变量。
  4. $projectArr是根叔组,其他数组全部是关联叔组,$rsyncArr设置rsync服务端参数,这个必须和$projectArr一一对应。
  5. 要做到同样的功能,这个脚本的NB程度已经是极限。
#!/usr/bin/env bash
dirPrefixPhp='/Users/Ares/Documents/Work/php'
excludeCommon="app/cache/* app/logs/*"
projectArr[0]=$dirPrefixPhp'/project1'
projectArr[1]=$dirPrefixPhp'/project2'
rsyncArr[0]='-e "ssh -p222" root@xxx.xxx.xxx.xxx:/srv/www/project1'
rsyncArr[1]='root@xxx.xxx.xxx.xxx:/srv/www/project2'
#wild card,seperated by space
exclude[0]=""
watchArgs=$*
if [ -z "$watchArgs" ];then
	watchArgs='.'
fi
fswatch --exclude=.git --exclude=.svn --exclude=.settings --exclude=.project --exclude=.buildpath $watchArgs|while read v;do
	if [ ! -e $v ];then
		continue
	fi
	for k1 in ${!projectArr[*]};do
		dirPrefix=${projectArr[$k1]}
		if [ "${v:0:${#dirPrefix}}" = "$dirPrefix" ];then
			path=${v#$dirPrefix}
			excludeK1=($excludeCommon' '${exclude[$k1]})
			if [ -n "$excludeK1" ];then
				for v2 in ${excludeK1[*]};do
					if [[ "${path:1}" == $v2 ]];then
						break 2
					fi
				done
			fi
			rsync='rsync -avz -R --chown apache:apache'
			rsync="cd ${projectArr[$k1]} && "$rsync' .'$path' '${rsyncArr[$k1]}' --no-p --no-t'
			dst=${rsyncArr[$k1]#*@}
			#dst=${dst%:*}
			echo -n '['`date +%H:%M:%S`'] '{projectArr[$k1]##*/}$path' => '$dst
			#echo -n '['`date +%H:%M:%S`']' $dst$path
			time=$( (time eval $rsync > /dev/null) 2>&1|head -n2|tail -n1|cut -f2)
			if [ 0 -eq $? ];then
				echo -ne " 33[32mok33[0m"
			else
				echo -ne " 33[31mfailed33[0m"
			fi
			echo '('${time:2}')'
		fi
	done
done

运行结果展示

project1/app/conf/app.ini => xxx.xxx.xxx.xxx:/srv/www/project1 ok(0.001s)
project2/app/conf/app.ini => xxx.xxx.xxx.xxx:/srv/www/project2 ok(0.003s)
project3/doc/sms.png => xxx.xxx.xxx.xxx failed(0.002s)

 

shell(bash) “time”输出

bashtime是一个很有用的命令,它可以为一段脚本或一个程序的执行计时,这通常在粗略比较程序执行效率的时候很方便。但是你会发现,time命令输出的时间文字不能被简单地重定向,例如重定向至一个文本文件,只能显示在屏幕上,这对于非交互计时很不方便。例如: 继续阅读