令狐虫的无聊空间

技术及生活笔记(8log是一种生活方式~~~)

导航

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

统计

公告

def run(level, a, b, c):
    if (level <= 1):
        return
    elif (level == 2):
        move(a, b)
        move(a, c)
        move(b, c)
    else:
        run(level-1, a, b, c)
        move(a, b)
        run(level-1, c, a, b)

档案

随笔分类

相册

其他好站

友情链接

登录

2007年4月11日

【公告】换地方了

本blog停止更新

敬请移步至 http://ch-linghu.3322.org/blog/

谢谢。

9:43 | 评论 (2)

2007年1月13日

[转贴不说话]态度

So this is the land I called it “homeland”, so this is the way they treat me, I’m always being constructive, I’m always being creative, I’m smart and I’m nice to everyone, I used to make wealth and knowledge for this land, but this land just cannot allow me to be a nice “good” man, so, what else can I do?

19:56 | 评论 (4)

2006年12月15日

Robocopy for TotalCommander

Total Commander 是我很喜欢的一个工具,现在已经越来越多使用开源软件的我,因为没有找到它的合适的替代品而不惜使用非注册版本。(其实我是给他们提交了注册申请的,不过不知道为什么一直没有答复,信用卡上的钱也没有少。写e-mail给他们也没有回音。等待了相当长一段时间之后,我只好放弃,继续用我的非注册版本,只是启动时点个按钮而已,也没什么大不了。)

但是Total Command在复制大文件的时候,却有一些令人相当不爽的问题,首先是它需要在复制前统计文件大小,当复制一个含有上千甚至上万个小文件的庞大的文件夹的时候,这个步骤往往会导致TC失去相应很长时间。另外,由于没有续传功能,在网络间拷贝时,如果网络出了问题,也只有从头来过。

我在Autodesk的时候,同事曾经介绍过一种优秀的文件拷贝工具:robocopy,当时是用来通过VPN从美国的服务器上拷贝项目文件。这种远程网络十分的不稳定,而且文件很多很大,经常会花上N个小时。为了不影响工作,也为了避免copy失败,我们都被推荐使用robocopy,在下班之后进行复制。它在复制文件方面效率很高,而且有断线重连、续传、制定schedule等高级功能,可谓功能强大。但是说来惭愧,用了很久robocopy,竟然搞不清它系出何门。上次Google了一下,发现微软的Resource Kit里有它的身影,想来大概还是微软自己的作品。不过我一般都是找那些重新包装的单独的版本——因为Resource Kit不支持Windows 2000。

robocopy其实很简单,只有一个exe文件,复制到windows目录下就可以使用。但是它毕竟是命令行工具,放着强大的TotalCommander不用,另开一个命令行窗口吭哧吭哧的输入文件名,总有些心不甘情不愿的感觉。于是今天趁着有空,顺手写了一个Python脚本,把robocopy和TotalCommander结合起来。

TotalCommand是可以增加工具栏按钮的,每个按钮可以执行TC内部命令,或者外部程序。程序还可以接受参数,其中,TotalCommander有一些预设参数,可以传递给目标程序。翻看TC的帮助可知:

? as the first parameter causes a Dialog box to be displayed before starting the program, containing the following parameters. You can change the parameters before starting the program. You can even prevent the program's execution.
?作为第一个参数,可以在程序运行前显示一个对话框,其中包含下面提到的参数。你可以在程序运行前改变这些参数,甚至阻止程序的运行。

%P causes the source path to be inserted into the command line, including a backslash (\) at the end.
%P 将源路径插入命令行,包含最后的反斜杠(\)。

%N places the filename under the cursor into the command line. 
%N 将在命令行的相应位置用光标所在位置的文件名(注:这里的意思是源窗口)替代。

%T inserts the current target path. Especially useful for packers.
%T 插入当前目标路径。对packers特别有用。


%M places the current filename in the target directory into the command line.
%M 将在命令行的相应位置用目标目录中的当前文件名替代

%O places the current filename without extension into the command line. 
%O 将在命令行的相应位置用当前的不含扩展名的文件名替代

%E places the current extension (without leading period) into the command line.
%E 将在命令行的相应位置用当前文件名的扩展名(不含前面的点号(.))替代

Note: %N and %M insert the long name, while %n and %m insert the DOS alias name (8.3). %P and %T insert the long path name, and %p and %t the short path name. (Same for %o and %e)
注意:%N和%M插入长文件名,而%n和%m插入DOS8.3格式的短文件名。%P和%T插入长路径名,%p和%t插入短路径名。(%o和%e也一样)

%% inserts the percent-sign.
%%插入一个百分号。

%L, %l, %F, %f, %D, %d create a list file in the TEMP directory with the names of the selected files and directories, and appends the name of the list file to the command line. The list is deleted automatically when the called program quits. 6 types of list files can be created:
%L, %l, %F, %f, %D, %d 在临时目录建立一个当前选中文件和目录的列表文件,并且把这个列表文件的名字加入到命令行。这个列表在调用程序退出的时候会被自动删除。有6种类型的列表文件可以被建立:

%L	Long file names including the complete path, e.g. c:\Program Files\Long name.exe
%L      包含完整路径的长文件名,例如c:\Program Files\Long name.exe

%l	(lowercase L) Short file names including the complete path, e.g. C:\PROGRA~1\LONGNA~1.EXE
%l	(小写的L) 包含完整路径的短文件名, 例如 C:\PROGRA~1\LONGNA~1.EXE

%F	Long file names without path, e.g. Long name.exe
%F	不包含路径的长文件名, 例如 Long name.exe

%f	Short file names without path, e.g. LONGNA~1.EXE
%f	不包含路径的短文件名, 例如 LONGNA~1.EXE

%D	Short file names including the complete path, but using the DOS character set for accents.
%D	包含完整路径的短文件名, 但是仅使用DOS字符集. (?)

%d	Short file names without path, but using the DOS character set for accents.
%d	不包含路径的短文件名,但是仅使用DOS字符集. (?)

robocopy的常用语法是 robocopy <源目录> <目标目录> <文件名集合>,比如 robocopy . \\192.168.0.1 cd1.rmvb cd2.rmvb。因此,我们需要三种参数:源目录名,目标目录名,源目录中选中的文件列表(不含路径)。

因为TotalCommander产生的选中文件列表是放在一个文件中而不是直接传送给程序,所以需要写一个脚本进行一下转换。

于是我就写了一个这样的Python脚本:

import sys
import os
import traceback

try:
    #get parameters pass from Total Command
    source, target, filelist_file = sys.argv[1:]
    filelist = open(filelist_file).readlines()

    #generate the cmd line for robocopy
    filelist_str = " ".join(['"%s"' % file[:-1] for file in filelist])
    cmd = 'robocopy "%(source)s" "%(target)s" %(flist)s /Z /MOV' % {"source":source, "target":target, "flist":filelist_str}

    #print the command line and then execute it
    print cmd
    os.system(cmd)
except:
    traceback.print_exc()

os.system("PAUSE")

在建立TotalCommander按钮的时候,使用下面的参数:

"%P " "%T " "%F "

注意第二个引号前面有一个空格,这是因为TC传过来的参数带“\”,而“\”和“"”组合表示另一个含义,就是没有特别意义的引号(跟C语言的解释类似),这样会造成参数解析错误,加了空格就没问题了。

其中这里robocopy的附加参数 /Z 表示允许续传,/MOV表示移动文件(复制完成后删除源文件)。这些都是我自己的需求。

这个脚本并没有考虑到选中的是目录的情形,在这种情况下执行会失败。但是凭借Python的能力,和robocopy的/MIR (全目录镜像复制)参数,写出支持选中目录复制的脚本应该是并不困难。

16:09 | 评论 (1)

2006年11月3日

【Linux】升级到Edgy

憋了好一阵子,终于还是决定升级了。

由于害怕初装Ubuntu时设置中文、安装驱动,apt-get一大堆组件等等的痛苦,我决定直接升级。

网上找了一下升级方法,其实说白了很简单:把/etc/apt/sources.list里的dapper改成edgy,然后sudo apt-get update,再sudo apt-get dist-upgrade即可。

(实际上,dist-upgrade要做两次,第一次做完之后重启,将会替换除了upstarter(系统启动组件)之外的所有组件,第二次则是替换upstarter)

整个升级过程基本上顺利,除了时间很长——差不多要3、4个小时。然后重启——嗯,也没什么问题,除了X起不来 -_-。

检查了一下log,发现是显卡驱动fglrx的问题。这个驱动是我自己从ati网站上下载安装的,不属于apt的升级范畴,因此不工作也是正常的。解决方法么也很简单,先去xorg.conf里把显卡驱动换成ati,让X跑起来再说(因为我要用Fx啊)。然后去ati网站下载新的fglrx驱动,chmod +x,运行……

结果很不如人所愿,出来一个Bad intstitution的错误。开始以为是忘了卸载之前的驱动造成的,卸载之后再试,结果还是一样。

只好再去网上查资料。终于在ubuntuforum里找到了答案:edgy的默认Shell改用了dash(这是什么?)而不是以前的bash,所以要安装之前先要把默认shell改成bash才行。

sudo mv /bin/sh /bin/SH
sudo ln -s /bin/bash /bin/sh

安装完之后再改回来就可以了。

昨天回家检查了一下,部分程序(如drscheme,d4x等等)升级后不能正常工作,需要卸载后重新安装。其他没有什么大问题,做了一点修修补补之后就跟以前一样了。

新的系统感觉启动和Gnome的速度都快了,不知道是不是心理作用。

9:14 | 评论 (2)

2006年11月2日

【除草帖】【技术】C++初始化列表问题及解决

很久没更新了。今天来除除草。

今天碰到一个问题,有这样一个类:

class CMonitorFactory
{
public:
   CMonitorFactory(CSelectReactor *reactor)
     : m_pReactor(reactor)
   {}
private:
  CSelectReactor *m_pReactor;
};

class CMonitorApi : public CMonitorFactory
{
public:
   CMonitorApi();
private:
   CSelectReactor *m_pReactor;
};

在写CMonitorApi实现的时候,我想当然的写成了(基本功不够扎实啊-_-):

CMonitorApi::CMonitorApi()
   : m_Reactor(new CSelectReactor()), CMonitorFactory(m_Reactor)
{}

结果实际运行的时候发现出错,跟踪发现CMonitorFactory的m_Reactor没有被初始化。突然意识到这是一个初始化顺序的问题:基类构造函数总是在成员变量之前初始化!

我一下子没了主意(由此发现我的C++知识还有欠缺),后来经过猛禽提醒,我意识到可以利用多重继承来解决这类问题。下面是解决方法:

class CMonitorApiHelper
{
public:
    CSelectReactor *m_pReactor;
    CMonitorApiHelper()
      : m_pReactor(new CSelectReactor())
    {}
};

//注意Helper必须在CMonitorFactory的前面
class CMonitorApi : public CMonitorApiHelper, public CMonitorFactory
{
public:
   CMonitorApi();
private:
   CSelectReactor *m_pReactor;
};

//Helper的构造函数将会被自动调用,不用显式写出
CMonitorApi::CMonitorApi()
   : m_Reactor(CMonitorApiHelper::m_Reactor), CMonitorFactory(CMonitorApiHelper::m_Reactor)
{}

16:44 | 评论 (6)


请不要发表可能给我们带来伤害的政治言论,谢谢配合