如何从 VMS 转移到 Linux (From VMS to Linux HOWTO) <author>By Guido Gonzato, <url url="guido ``at'' ibogeo.df.unibo.it">, and Mike Miller, <url url="miller5@uiuc.edu">, 译者:峰舟 <date>v1.1.3, 17 September 1999 <abstract> 这份 HOWTO 主要是针对那些已经用过 VMX 系统,而现在可能因需要而转型使用 Linux 作业系统的人。 希望藉由比较两者作业系统间指令的差异,而循序渐进的带领您进入 Linux 的世界。 </abstract> <toc> <sect> 简介 <label id="Introduction"> <sect1> 为何要使用 Linux ? <p> 您曾经听过 UNIX 艰深难懂便畏惧丢开 VMS 吗?别烦恼,Linux,最好的 UNIX 相容机种之一, 一点也不会比 VMS 难使用;相反的,我发现 Linux 比 VMS 更容易上手。虽然,VMS 迷可能不以为然, 但是,经过许多人的建议是:Linux 确实是比 VMS 更有效力且更是多功。 Linux 和 VMS 两者都是很好的作业系统,而且本质上都可以非常有效率的完成相同的作业。 但是,Linux 有一些非常吸引人的特色,而使得她成为 VMS 很好的另一个选择。并且, Linux 可以在个人电脑 (PC) 上使用,而 VMS 却不行。现在任何一台奔腾(Pentium)的电脑, 使用 Linux 为作业系统的效能更可远远地胜过 VMS 的机器。更迷人的是,现在以一般的显示卡, 就可以有非常优秀的视窗图形界面。几乎总是快过那些专用的电脑。 我想,您应该是大学里的研究人员或是学生,并且您每天使用 VMS 来完成下列的几件事: <itemize> <item> 使用 TeX/LaTeX 来写报告; <item> 使用 Fortran 来写程式; <item> 作一些图形文件; <item> 上网使用某些服务; <item> 及其他等等. </itemize> 在下面的章节中,我将利用您在 VMS 上的经验,介绍如何在 Linux 上完成上列的每一件事。 首要事物: <itemize> <item> 请确定 Linux 和 X Window 都已经安装完全; <item> 有一位系统管理员可以作为技术指导。(请找他们帮忙,请不要来找我 ;-) ); <item> 您系统上的 shell 可以是 bash (请询问您的系统管理员); </itemize> 请注意,这份 HOWTO 还不足够使您全部了解 Linux 的精髓。她只包含了仅有的一些入门的必要知识而已。 您应该学习更多的 Linux 的知识,并且充分的利用她。(advanced <tt/bash/ features, programming, regular expressions...). 从现在开始,RMP 的意思是 `please read the man pages for further details'. 在 Linux 上,man pages 其实就是 help 的意思。 The Linux Documentation Project 文件可以在 <url url="ftp://sunsite.unc.edu:/pub/Linux/docs/LDP">, 获得。而这也是重要讯息的来源。 我建议您可以阅读由 Larry Greenfield 写的 ``Linux User Guide'' 书。---这是一本非常适合初学者的入门书。 现在让我们步入正题吧: <sect1> 指令的比较和档案格式 <p> 这个表列出 VMS 和 Linux 中常用的指令集。请牢记在心,其语法也将大大的不同。 详细细节请参考相关章节。 <tscreen><verb> VMS Linux 注意事项(Linux 部份) ------------------------------------------------------------------------------ @COMMAND command 必须可被执行 COPY file1 file2 cp file1 file2 CREATE/DIR [.dirname] mkdir dirname 一次只能建一个目录 CREATE/DIR [.dir1.dir2] mkdirhier dir/name DELETE filename rm filename DIFF file1 file2 diff -c file1 file2 DIRECTORY ls DIRECTORY [...]file find . -name file DIRECTORY/FULL ls -al EDIT filename vi filename, 您可能不会喜欢使用 vi emacs filename, EDT compatible jed filename ditto---my favourite FORTRAN prog.for g77 prog.f, 不需要作 LINK f77 prog.f, fort77 prog.f HELP command man command must specify `command' info command ditto LATEX file.tex latex file.tex LOGIN.COM .bash_profile, `hidden' file .bashrc ditto LOGOUT.COM .bash_logout ditto MAIL mail, 最原始的 email 程式 elm, 比 mail 好。 pine 不错,但是都只能处理文字。 PRINT file.ps lpr file.ps PRINT/QUEUE=laser file.ps lpr -Plaser file.ps PHONE user talk user RENAME file1 file2 mv file1 file2 not for multiple files RUN progname progname SEARCH file "pattern" grep pattern file SET DEFAULT [-] cd .. SET DEFAULT [.dir.name] cd dir/name SET HOST hostname telnet hostname, 不太相同 rlogin hostname SET FILE/OWNER_UIC=joe chown joe file 完全不相同 SET NOBROADCAST mesg SET PASSWORD passwd SET PROT=(perm) file chmod perm file 完全不相同 SET TERMINAL export TERM= 语法不同 SHOW DEFAULT pwd SHOW DEVICE du, df SHOW ENTRY lpq SHOW PROCESS ps -ax SHOW QUEUE lpq SHOW SYSTEM top SHOW TIME date SHOW USERS w STOP kill STOP/QUEUE kill, 针对 processes lprm 针对 print queues SUBMIT command command & SUBMIT/AFTER=time command at time command TEX file.tex tex file.tex TYPE/PAGE file more file less file much better </verb></tscreen> 当然,这不只是指令的名称不一样而已,请继续读之。 <sect> 牛刀小试 <label id="Short Intro"> <p> 这些绝对是您在第一次登入系统前必须知道的一些事情,放轻松,不会太复杂的。 <sect1> 档案 <p> <itemize> <item> 在 VMS 上的档名的表示法是 <tt/filename.extension;version/。 但是在 Linux 上,档案的版本号码将不会再出现(重要的限制,请参阅 <ref id="Numbered Backups Under Linux" name="Linux 上的档案版本">); 档名最常只能有 255 个字元,档名中可以出现很多个点 “.”。例如:<tt/This.is_a_FILEname.txt/. <item> Linux 对档名的大小写是有分别的: <tt/FILENAME.txt/ 和 <tt/filename.txt/ 是两个完全不一样的档名; <tt/ls/ 是一个指令,可以被执行,但是 <tt/LS/ 却不是指令,会出现错误讯息。 <item> 档名的第一个字元如果是一点“.”,则这个档名是`隐藏档' (也就是说,如果不加特别指令的话,一般的 ls 将不会显示出这些隐藏档), 而档案的结尾如果是“蚯蚓号”'<tt/&tilde/' ,这表示备份档案(或是暂存档). </itemize> 现在,下表整理出把 VMS 的指令对应到 Linux 上的指令. <tscreen><verb> VMS Linux --------------------------------------------------------------------- $ COPY file1.txt file2.txt $ cp file1.txt file2.txt $ COPY [.dir]file.txt [] $ cp dir/file.txt . $ COPY [.dir]file.txt [-] $ cp dir/file.txt .. $ DELETE *.dat;* $ rm *dat $ DIFF file1 file2 $ diff -c file1 file2 $ PRINT file $ lpr file $ PRINT/queue=queuename file $ lpr -Pprintername file $ SEARCH *.tex;* "geology" $ grep geology *tex </verb></tscreen> 其他对於目录方面的指令,请见一章节;档案的属性(protections, ownership...)请参照 <ref id="Advanced Topics" name="进阶">。 <sect1> 目录 <p> <itemize> <item> 在同一个节点(node)或是装置(device),在 VMS 上,目录的形式看起来应该像这样:<tt/[top.dir.subdir]/; 在 Linux 上是:<tt>/top/dir/subdir/</tt>. 对上层的目录我们称为“根目录”(<tt>/</tt>); 所有子目录,都是由根目录向下延伸: <tt>/bin</tt>, <tt>/usr</tt>, <tt>/tmp</tt>, <tt>/etc</tt>, 等等。 <item> 目录名称 <tt>/home</tt> 是存放使用者目录,例如:<tt>/home/guido</tt>, <tt>/home/warner</tt>, 等等。 当使用者登入的时候,她们会登入到她们自己拥有的使用者目录;这和 <tt/SYS$LOGIN/ 是有异曲同工之妙。 切换到只用者目录有个方便的方法:使用“蚯蚓号”'<tt/&tilde/'。 所以,<tt>cd ˜/tmp</tt> 和 <tt>cd /home/guido/tmp</tt> 是一样的意思。 <item> 目录名称的命名方式和档案名称的命名方式相同。 再者, 每个目录都会有两个特别的目录名称:一个是:<tt/./ ,表示指到自己的目录。 (像 <tt/[]/); 一个是:<tt/../ ,表示指到上一层目录 (像 <tt/[-]/)。 </itemize> 让我们来看看其他的例子: <tscreen><verb> VMS Linux --------------------------------------------------------------------- $ CREATE/DIR [.dirname] $ mkdir dirname $ CREATE/DIR [.dir1.dir2.dir3] $ mkdirhier dir1/dir2/dir3 n/a $ rmdir dirname (if dirname is empty) $ rm -R dirname $ DIRECTORY $ ls $ DIRECTORY [...]file.*;* $ find . -name "file*" $ SET DEF SYS$LOGIN $ cd $ SET DEF [-] $ cd .. $ SET DEF [top.dir.subdir] $ cd /top/dir/subdir $ SET DEF [.dir.subdir] $ cd dir/subdir $ SHOW DEF $ pwd </verb></tscreen> 对於档案的属性(protections, ownership),还有一些进阶主题,请参照 <ref id="Advanced Topics" name="进阶">. <sect1> 程式 <p> <itemize> <item> 指令,编译过的程式(执行档),和 shell scripts (VMS 上的 `command files') 并没有强制规定需要有特定的副档名。 像 <tt/.EXE/ or <tt/.COM/ 等,只要您喜欢,您想要她叫什麽名字都可以。 如果您使用 <tt/ls -F/ 来察看执行档的时候,您会发现执行档会被标示成 '<tt/*/' 。 <item> 欲执行可执行的程式,只要输入指令名称就可以了。(没有所谓的 <tt/RUN PROGRAM.EXE/ 或是 <tt/@COMMAND/)。 注意:这个执行档必须指定某路径。基本上,预设录经包含了 <tt>/bin</tt>, <tt>/usr/bin</tt>, <tt>/usr/X11R6/bin</tt>, 等等。 如果,您自己写了一个程式, 您可以将这个程式放在您自己的预设路径中(如何操作,请参照 <ref id="Configuring" name="设定">)。 或是您也可以指定一个绝对路径来执行这只程式,例如:<tt>/home/guido/data/myprog</tt>; 或是 使用相对路径 <tt>./myprog</tt> 。 <item> 指令的参数在 VMS 上是使用 <tt>/OPTION=</tt> 来完成,而在 Linux 上, 我们使用 <tt/-switch/ 或是 <tt/--switch/ (<tt/switch/ 参数可能是一个字元,许多字的组合,或是一个字)。 比较特别的,参数 <tt/-R/ (recursive) 在 Linux 上和 在 VMS 上 <tt/[...]/ 扮演著相同的功能; <item> 在命令列中,您可以一次下很多个指令: <tscreen><verb> $ command1 ; command2 ; ... ; commandn </verb></tscreen> <item> Linux 大部分的弹性来自於两个特性,而这两个特性在 VMS 上却很难被表示出来,或是根本就没有。 她们分别是:I/O 重导(redirection) 和 管道 (piping)。 (曾经有人告诉我最近的 DCL 版本有支援重导(redirection)和管道(piping), 可是我没有那个版本)。重导(redirection) 在 VMS 上只是从属的特徵(像指令里的参数 <tt>/OUTPUT=</tt> ), 或是一个难讨好的行程(process)。 例如: <tscreen><verb> $ DEFINE /USER SYS$OUTPUT OUT $ DEFINE /USER SYS$INPUT IN $ RUN PROG </verb></tscreen> 在 Linux 就只要这样就可以达成: <tscreen><verb> $ prog < in > out </verb></tscreen> Piping 实际上在 VMS 上并没有提供,但是在 Linux 却是一个重要的角色。 典型的例子如下: <tscreen><verb> $ myprog < datafile | filter_1 | filter_2 >> result.dat 2> errors.log & </verb></tscreen> 意思是说:程式 <tt/myprog/ 导入一个档案为 input (由 “<tt/</”读入档案 <tt/datafile/)。 其执行後的结果被转为(pipe)另一个程式(filter_1) 的 input,处理後得到的结果再转为另外一只程式(filter_2)的 input, 再作进一步的处理後,最後的结果被附加到 result.dat 档案上,将错误讯息覆盖到 errors.log 的档案上。 而这一切的动作,都在背景执行。 想要看更精彩的例子,请参照 <ref id="Examples" name="实例">. </itemize> 对於多工,`queues', 或其他类似主题,请参阅 <ref id="Advanced Topics"name="进阶">. <sect1> 快速浏览 <label id="Quick Tour"> <p> 现在您可以来试试 Linux 的威力了。输入您的 login name 和 password。假设您的 login name 是 <tt/john/ ,Password 是 <tt/My_PassWd/, <em/不要/ 输入 <tt/John/ 或是 <tt/my_passwd/。 记住,大小写对 Unix 来说,是不同的意思。 一当您登入後,您就会看到系统提示符号(prompt);可能看起来像 <tt/machinename:$/。 如果您想更改您的系统提示符号,或是在您一 Login 後就自动执行一些程式,您可能需要去编辑一个隐藏档(<tt/.profile/ 或是 <tt/.bash_profile/)。 (实例请参照“组态设定”一章节 <ref id="Configuring" name="设定">)。 这和 VMS 上的<tt/LOGIN.COM/ 有异曲同工之妙。 您可以使用 ALT--F1, ALT--F2, ... ALT--F6 来切换六个 `virtual consoles'。 当您其中的一个 virtual consoles 正在忙於处理某一只程式的时候,您可以任意的切换到任何一个 virtual consoles 继续您其他的工作。 试著切换登入到其他的 virtual consoles 吧! 现在您可能想要开始执行 X Windows 了吧(以後我们简称为 X)。X 是图形界面环境, 有点像 DECWindows --- 实际上,DECWindows 是衍生自 X Window system. 请输入 <tt/startx/ 并且等待几秒您将会看到 <tt/xterm/ 或是其他类似的终端机模拟程式被开启, 可能还会有一个工作列。(视您系统管理员如何设定,不一样的设定,所看到的结果将会不同)。 试著在桌面上同时按下滑鼠的左右键,您可以看到一个弹跳视选单出现(滑鼠按键的功能也因设定不同而有不同的功能)。 进入 X 後,如果想要执行文字模式的终端机 (`console') 同时按住下列任一组按键: CTRL--ALT--F1 ... CTRL--ALT--F6 (需要同时按)。是看看!如果想要跳回视窗界面,可以 同时按下 ALT--F7 就可以了。欲结束 X ,这著选单上的 exit 选项结束,或是同时按下 CTRL--ALT--BS. 输入下列指令,可以列出您现在目录下的档案(包括隐藏档): <tscreen><verb> $ ls -al </verb></tscreen> 按 SHIFT--PAG UP 可以往回卷到以前的萤幕。 现在我们来看看指令 <tt/ls/ 的说明档(help), 输入: <tscreen><verb> $ man ls </verb></tscreen> 按下 'q' 可以跳出。如果要登出,可以输入 <tt/exit/ 登出目前终端机。 如果想要关机,可以同时按下 CTRL--ALT--DEL 并且等带数秒就可以了。 (<em/注意:/ 绝对不要直接就关掉您电脑上的电源,请按照一定的关机程序才可以关掉电源,不然可能会伤害到档案系统)。 如果您想您已经可以上路了,那就放手去作吧!但是,如果我是您的话,可会先跳到进阶主题这一章节: <ref id="Advanced Topics"name="进阶">. <sect> 档案编辑 <label id="Editing Files"> <p> Linux 没有 <tt/EDT/ 编辑器,但是有很多的编辑器选择可供使用。 在所有UNIX 系统中,唯一保证一定有<tt/vi/ 这个编辑器---算了吧, 您的系统管理员一定已经安装比 vi 更好用的编辑器了。可能比较受欢迎的编辑器是 <tt/emacs/,这可以用来模拟 VMS 上的 <tt/EDT/ ; <tt/jed/ 是另一种类似 <tt/EDT/ 的编辑器。 这两种编辑器用来编写程式码相当的实用,因为她们有两个 <tt/EDT/ 没有的功能: 高亮度相关字(syntax hilighting)和自动缩排(automatic indentation)。 而且,您可以不需要跳出编辑器,就可以直接在编辑器里编译(Compile)您的程式。 (command <tt/ESC-X compile/); 如果有语法错误,游标将会自动跳到有错误的地方。 我敢打赌您将不会想再看到那只有蓝色的 <tt/EDT/ 了。 如果您有 <tt/emacs/: 启动她,然後输入 <tt/ESC-X edt-emulation-on/。 键入 ALT--X or ESC-X 可以跳出 <tt/emacs/,像 <tt/EDT/ 的 CTRL--Z。 从现在开始,<tt/emacs/ 就像 <tt/EDT/ 一样,除了一些指令不太一样。 不同处: <itemize> <item> <em/不行/ 使用 CTRL--Z 来执行命令列指令。 (如果您做了,您的 emacs 将会停止工作, 不过您可以试著输入 <tt/fg/ 来继续您的 emacs); <item> Emacs 有大量的线上说明(on-line help)。按 CTRL-H ?, 或是 CTRL-H T 启动。; <item> 存档: CTRL-X CTRL-S; <item> 离开: CTRL-X CTRL-C; <item> 新增一个档案: CTRL-X CTRL-F, 然後 CTRL-X B 可以在个档案中作切换。 </itemize> 如果您有 <tt/jed/: 可以请您的系统管理员恰当地设定 <tt/jed/ 。 当您启动她後,模拟器就已经自动载入。可以使用 CTRL--H CTRL--H or CTRL-? 启动线上说明。指令部份,大致上和 <tt/emacs/ 相同。 此外, 还有一些易於操作的操作键没有被装订在原来的 <tt/EDT/ 中; 这些操作键可以依您的个人喜好自行设定,请询问您的系统管理员。 或许您可能会使用另一个完全不一样操作界面的编辑器。但是 <tt/emacs/ 直觉上会是一个不错的选择。 另一个十分受欢迎的编辑器是:<tt/joe/, 她可以模拟其他编辑器,像 <tt/emacs/ 。 (甚至更容易上手) 或是 Dos 的编辑器。 启动这个编辑器就像 <tt/jmacs/ 或是 <tt/jstar/ 一样, 可以使用 CTRL-X H 或是 CTRL-J 得到丰富的线上说明。 <tt/emacs/ 和 <tt/jed/ 比 <tt/EDT/ 更具有威力。 <sect> TeXing <label id="TeXing"> <p> TeX 和 LaTeX 在 Linux 上完全和 VMS 一样---不同的地方是,Linux的执行速度更快 :-), 这个工具用来处理 <tt/.dvi/ 和 <tt/.ps/ 的档案更俱优势: <itemize> <item> 由 TeX 执行 TeX 档,就像平常一样: <tt/tex file.tex/; <item> 转换 <tt/.dvi/ 挡到 <tt/.ps/ 档,输入 <tt/dvips -o filename.ps filename.dvi/; <item> 检视 <tt/.dvi/ 档,在 X Window 下输入: <tt/xdvi filename.dvi &/. 在显示页按下滑鼠可以放大。 这是一个智慧型的程式:如果您编辑且执行 TeX 产生一个较新版本的 <tt/.dvi/ 档案,<tt/xdvi/ 会自动更新; <item> 检视 <tt/.ps/ 档, 在 X Window 下输入 <tt/ghostview filename.ps &/. 按滑鼠可以缩放。 全部的档案或是部份档案可以被列印出来。 然而还有一个比 TeX 更好的程式:<tt/gv/. <item> 列印 <tt/.ps/: 通常指令是 <tt/lpr mypaper.ps/ ,但是如果 PostScript 列表机被呼叫(假设使用 ps 指令) 您将会是执行: <tt/lpr -Pps mypaper.ps/。对於更多有关 print queues 的讯息,请参照 <ref id="Print Queues" name="列印埠">. </itemize> <sect> 程式 <label id="Programming"> <p> 在 Linux 上写程式更是舒服:有许多好用得工具可以让写程式更加快速更加简单。 例如:写程式无非是单调沈闷的工作:编辑--存档--离开--编译--重新编辑 一直反覆的执行同样的动作。 但是,如果使用像 <tt/emacs/ 或是 <tt/jed/ 等工具,上述那些动作,将统一整合在编辑器里,一次完成。 <sect1> Fortran <p> 大体上,没有多大的差别,但是请注意,这个免费的编译器可不是百分之百的和 VMS 相容的。 可能会有些奇怪的结果发生。(实际上,VMS 的 Fortran 编译器并不是一个可以标准延伸的(non-standard))。 详细情形请看 <tt>/usr/doc/g77/DOC</tt> or <tt>/usr/doc/f2c/f2c.ps</tt> 。 您的系统管理员已经安装了一个叫做 <tt/g77/ 的 compiler (不错但是, 在 0.5.21 版, 还是没有完全和 DEC 的 Fortran 百分百地相容) ,或是一个把 Fortran 转成 C 语言的转换器,叫做 <tt/f2c/。 加上她的一个前端(front-ends)装置,模拟就像是一个 Fortran 编译器。 依我的经验,<tt/yaf77/ 套件提供最好的解决方案。 欲使用 <tt/g77/ 来 compile 您的 Fortran 程式, 先用任意编辑记编辑程式码,以副档名 <tt/.f/ 存档, 然後执行如下: <tscreen><verb> $ g77 myprog.f </verb></tscreen> 她会自动帮您产称 <tt/a.out/ 的执行档。(您不需要作任何 link 的动作) 如果想要产生不同的执行档档名,可以下参数: <tscreen><verb> $ g77 -O2 -o myprog myprog.f </verb></tscreen> 请注意最佳化!要求您的系统管理员细读编译器的说明文件,并且告知您是否还有任何的存在问题。 编译中间码(subroutine): <tscreen><verb> $ g77 -c mysub.f </verb></tscreen> 这会产生 <tt/mysub.o/ 这个档案。 然後您需要作连结(link)的动作。 <tscreen><verb> $ g77 -o myprog myprog.f mysub.o </verb></tscreen> 如果您想作成函数库(library),您可以这样作: <tscreen><verb> $ cd subroutines/ $ cat *f >mylib.f ; g77 -c mylib.f </verb></tscreen> 这会产生出 <tt/mylib.o/ ,您可以使用她来连结您的程式。 最後,如果要 link 其他的函数库(library),我们假设 <tt/libdummy.so/: <tscreen><verb> $ g77 -o myprog myprog.f -ldummy </verb></tscreen> 如果您使用 <tt/f2c/, 您只能使用 <tt/f77/ 或是 <tt/fort77/ ,而不能使用 <tt/g77/。 另一个有用的工具是 <tt/make/, 详述如下: <sect1> 如何使用 <tt/make/ <p> <tt/make/ 可以用来编辑很多分散於个档案的原始码。在 VMS 上我们称为 <tt>MMS</tt> 和 <tt>MMK</tt>, 但是她们和 Linux 有不同的语法。 假设您有一些原始程式,需要作些例行程序。程式分别为 <tt/file_1.f, file_2.f, file_3.f/, 主程式为 <tt/myprog.f/。 如果您是手动编译您的程式,每当您修改您的程式码後, 您必须知道哪个档案和哪个档案有关连,哪个档案必须先编译,等等。 与其发疯,不如您可以写个 `makefile'。 这是一个文字档,里面记录著您程式码与程式码之间的关连性。 当其中一个档案被修改後,只有与这个被修改的档案有相关的档案需要被重新编译。 例如,您写了一个 makefile 如下: <code> # 这是一个 makefile # 使用 <TAB> 键,当您见到 <TAB> 标签时! # 这非常的重要,请不要使用空白键代替。 myprog: myprog.o file_1.o file_2.o file_3.o <TAB>g77 -o myprog myprog.o file_1.o file_2.o file_3.o # myprog depends on four object files myprog.o: myprog.f <TAB>g77 -c myprog.f # myprog.o depends on its source file file_1.o: file_1.f <TAB>g77 -c file_1.f # file_1.o depends on its source file file_2.o: file_2.f file_1.o <TAB>g77 -c file_2.f file_1.o # file_2.o depends on its source file and an object file file_3.o: file_3.f file_2.o <TAB>g77 -c file_3.f file_2.o # file_3.o depends on its source file and an object file # end of makefile. </code> 储存这个档案,命名为 <tt/Makefile/ 且在命令列输入 <tt/make/ 来编译您的程式; 或是您也可以将她存成 <tt/myprog.mak/ 然後使用 <tt/make -f myprog.mak/ 来编译. 接下来的後续动作, RMP.(还记得什麽是 RMP 吧!) <sect1> Shell Scripts <p> Shell scripts 就像 VMS 上的 command files。, 这可以建构出非常有用的功能。 要写一个 script, 您所要作的就只是写一个包含一些指令的文字档,然後存档,改变成可执行的模式 (使用 <tt/chmod +x <scriptfile>/)。 只要输入该 Script 的名字就可以执行了。 写一个 Script 是一个非常重大的工程,这需要一本书。这里我就不再多做说明了。 我只给您一个或多或少的综合的(希望)有用的例子,您或许可以从这个例子中得到一些基本的规则。 EXAMPLE: sample.sh <code> #!/bin/sh # sample.sh # I am a comment # 不要修改第一行,她必须以这种形式存在在第一行!!! echo "This system is: `uname -a`" # use the output of the command echo "My name is $0" # built-in variables echo "You gave me the following $# parameters: "$* echo "First parameter is: "$1 echo -n "What's your name? " ; read your_name echo notice the difference: "hi $your_name" # quoting with " echo notice the difference: 'hi $your_name' # quoting with ' DIRS=0 ; FILES=0 for file in `ls .` ; do if [ -d ${file} ] ; then # if file is a directory DIRS=`expr $DIRS + 1` # this means DIRS = DIRS + 1 elif [ -f ${file} ] ; then FILES=`expr $FILES + 1` fi case ${file} in *.gif|*jpg) echo "${file}: graphic file" ;; *.txt|*.tex) echo "${file}: text file" ;; *.c|*.f|*.for) echo "${file}: source file" ;; *) echo "${file}: generic file" ;; esac done echo "there are ${DIRS} directories and ${FILES} files" ls | grep "ZxY--!!!WKW" if [ $? != 0 ] ; then # exit code of last command echo "ZxY--!!!WKW not found" fi echo "enough... type 'man bash' if you want more info." </code> <sect1> C 语言<label id="C"> <p> Linux 是一个写 C语言的好地方。就假设您会C语言吧!这里也几个指导方针。 编译您的程式<tt/hello.c/ ,您会使用到 <tt/gcc/ compiler, 这已是 Linux 的一部份了。 而且和 <tt/g77/ 有相同的使用方法: <tscreen><verb> $ gcc -O2 -o hello hello.c </verb></tscreen> 连结(link)函数库(library),加入参数 <tt>-l<libname></tt>。 例如,要 link 数学函数库和最佳化,可以下如下指令: <tscreen><verb> $ gcc -O2 -o mathprog mathprog.c -lm </verb></tscreen> ( <tt>-l<libname></tt> 参数强迫 <tt/gcc/ 连结(link)函数库(library) <tt>/usr/lib/lib<libname>.a</tt>; 所以 <tt/-lm/ 就连结了 <tt>/usr/lib/libm.a</tt>). 如果您的程式是由许多档案组成的,您可能也需要使用前面所提到的 <tt/make/ 这个工具。 在 makefile 使用 <tt/gcc/ 和 C语言的原始码档案就可以了。 您也可以获得有关 C 语言的函数的说明。这些说明文件都已经被编成 man pages,第三节(section 3) 了。 例如: <tscreen><verb> $ man 3 printf </verb></tscreen> 同时,有许许多多的函数库可供使用。其中您第一想要使用的是 <tt/ncurses/, 这可以用来处理文字模式下的特效。或是 <tt/svgalib/, 这可以用来处理图形模式。 <sect> 图形界面 <label id="Graphics"> <p> 在许多图形套件中,<tt/gnuplot/ 真是其中之翘楚。进入 X Window 後输入 <tt/gnuplot/, 可是著读入两个□例档: <tt/2D-data.dat/ (每行有两笔资料), 和 <tt/3D-data.dat/ (每行有三笔资料). 例:2-D graphs: <tscreen><verb> gnuplot> set title "my first graph" gnuplot> plot '2D-data.dat' gnuplot> plot '2D-data.dat' with linespoints gnuplot> plot '2D-data.dat', sin(x) gnuplot> plot [-5:10] '2D-data.dat' </verb></tscreen> 例:3-D graphs (每一行中的资料以空白键最为分隔): <tscreen><verb> gnuplot> set parametric ; set hidden3d ; set contour gnuplot> splot '3D-data.dat' using 1:2:3 with linespoints </verb></tscreen> 只有一行资料的档案(如时间序列)也可以被绘制成 2-D 的图形: <tscreen><verb> gnuplot> plot [-5:15] '2D-data-1col.dat' with linespoints </verb></tscreen> 或是绘成 3-D graph : <tscreen><verb> gnuplot> set noparametric ; set hidden3d gnuplot> splot '3D-data-1col.dat' using 1 with linespoints </verb></tscreen> 列印图形:假设您的 Postscript 列表机的指令是 <tt/lpr -Pps file.ps/,步骤如下: <tscreen><verb> gnuplot> set term post gnuplot> set out '| lpr -Pps' gnuplot> replot </verb></tscreen> 然後输入 <tt/set term x11/ 回复成 x11 模式。 别怀疑,当您离开 <tt/gnuplot/ 後,文件将会自动列印出来。 更多讯息,可输入 <tt/help/ 或是参见目录中的□例。 (<tt>/usr/lib/gnuplot/demos/</tt>) <sect> Mail 和 Internet 工具 <label id="Mail and Internet Tools"> <p> 因为网路是诞生在 Unix 的机器上,您可以在 Linux 上发现许多好用且易上手的软体。 者里所列,只是其中的一部份而已: <itemize> <item> <bf/Mail/: 使用 <tt/elm/ 或是 <tt/pine/ 来处理您的 email; 这两个应用程式都有线上说明(Online Help)。 对於较短的讯息,您可能使用 <tt/mail/, 如 <tt/mail -s "hello mate" user@somewhere < msg.txt/. 您可能会爱上像 <tt/xmail/ 这样的应用程式,或是类似的程式。 <item> <bf/Newsgroups/: 可使用 <tt/tin/ 或是 <tt/slrn/, 两者都是直觉式,且自我解读(self-explanatory). <item> <bf/ftp/: 欲脱离文字界面的 <tt/ftp/ 应用程式, 要求您的系统管理员安装全萤幕(full-screen)模式的 ftp 软体,如 <tt/ncftp/ , 或是图形界面的 <tt/xftp/. <item> <bf/WWW/: 普遍存在的 <tt/netscape/, 或是 <tt/xmosaic/, <tt/chimera/, 和 <tt/arena/ 都是图形界面的浏览器。另外还有一个文字界面的浏览器 <tt/lynx/, 非常的快速而且又有效率。 </itemize> <sect> 进阶 <label id="Advanced Topics"> <p> 到这个阶段,游戏就比较复杂了。学完这些东西,您就可以说,我懂一些 Linux 的东西 ;-) <sect1> 允许权(Permissions) 及 所有权(Ownership) <label id="Permissions"> <p> 档案和目录都有允许权(Permission) (即 VMS 上的 `protections') 和所有权(ownership), 这个观念不难理解,因为 VMS 上也有。如果您不能执行一只程式,或是您不能修改某一档案, 或是不能进入某目录,这是因为您没有被赋予使用这些资源的权力的关系(没有允许权), 或者是这个档案的根本就不属於您的(没有所有权), 让我们看看下面的例子吧: <tscreen><verb> $ ls -l /bin/ls -rwxr-xr-x 1 root bin 27281 Aug 15 1995 /bin/ls* </verb></tscreen> 第一个栏位显示出这个档案的使用权限 <tt/ls/ (拥有者(owner) 是 root, 群组(group) 是 bin). 拥有权可以分成三种模式: 拥有者(owner), 群组(group), 和 其他使用者(others)。 (和 VMS 的 owner, group, world 相似);有三种不同的允许权(permissions): 读(read), 写(write) (包含移除(delete)), 和执行(execute). 从左到右,<tt/-/ 是档案模式 (<tt/-/ = 一般档案(ordinary file), <tt/d/ = 目录(directory), <tt/l/ = 连结(link), 等); <tt/rwx/ 是允许档案拥有者可以对该档案作读,写,和执行的动作; <tt/r-x/ 是允许群组使用者可以对该档案作读和执行的动作,但是不可以作写的动作。; <tt/r-x/ 是限制其他的使用者对该档案只有读和执行的权限,却没有写的权限。 如何改变档案的使用权限: <tscreen><verb> $ chmod <whoXperm> <file> </verb></tscreen> 其中 who 是 <tt/u/ (user(使用者), 即档案的拥有者), <tt/g/ (群组 group), <tt/o/ (其他 other), X 表示可以为 <tt/+/ 或 <tt/-/, perm 可以为 <tt/r/ (读 read), <tt/w/ (写 write), 或是 <tt/x/ (可执行 execute). 举例说明: <tscreen><verb> $ chmod u+x file </verb></tscreen> 这是针对该档案,开放可执行的权限给该档案的拥有者。可缩写成: <tt/chmod +x file/. <tscreen><verb> $ chmod go-wx file </verb></tscreen> 这是对该档案,移除群组使用者和其他使用者对该档案的“写”的权限和“执行”的权限。 <tscreen><verb> $ chmod ugo+rwx file </verb></tscreen> 这是开放该档案的读,写,和执行的权限给所有的使用者。 另一个快速表示法为使用一组数字:<tt/rwxr-xr-x/ 可以用 755 来表示 (每一位数字对应一个控制位元: <tt/---/ 表是 0, <tt/--x/ 表示 1, <tt/-w-/ 表示 2...). 所以,rwx = 4+2+1 = 7,r-x = 4+0+1 = 5,所以,<tt/rwxr-xr-x/ 可以用 755 来表示。 对目录而言,<tt/rx/ 表示您可以切换到该目录: <tt/cd/ , 而 <tt/w/ 表示您可以删除该目录的档案(当然需要视该档案的使用权限而定), 或是目录本身. 这些还只是冰山的一角而已,想要知道更多---RMP. 如何改变档案的拥有权: <tscreen><verb> $ chown username file </verb></tscreen> 我整理成下表: <tscreen><verb> VMS Linux Notes ------------------------------------------------------------------------------ SET PROT=(O:RW) file.txt $ chmod u+rw file.txt $ chmod 600 file.txt SET PROT=(O:RWED,W) file $ chmod u+rwx file $ chmod 700 file SET PROT=(O:RWED,W:RE) file $ chmod 755 file SET PROT=(O:RW,G:RW,W) file $ chmod 660 file SET FILE/OWNER_UIC=JOE file $ chown joe file SET DIR/OWNER_UIC=JOE [.dir] $ chown joe dir/ </verb></tscreen> <sect1> 多工(Multitasking): 程序(Processes) 和 工作(Jobs) <label id="Multitasking"> <p> 欲执行很多程式,在 Linux 上没有所谓的 `batch queues' ; 多工其实以非常不一样的手法处理。 以下是一般常见的命令列: <tscreen><verb> $ command -s1 -s2 ... -sn par1 par2 ... parn < input > output & </verb></tscreen> 其中 <tt>-s1</tt>, ..., <tt>-sn</tt> 是该程式的参数(switch), <tt/par1/, ..., <tt/parn/ 是程式的输入变数(parameters). 现在让我们来看看在 Linux 上如何多工。程序(processes)是一只不论在前景或是背景被执行的程式。 <itemize> <item> 在背景执行程序: <tscreen><verb> $ progname [-switches] [parameters] [< input] [> output] & [1] 234 </verb></tscreen> shell 会提示您该程序(process)的工作号码(`job number') (第一个数字; 请看下文) 和该程序的程序识别码 PID (Process IDentifier). 每一个程序都有一组独一无二的 PID. <item> 检视有多少 Processes 被执行: <tscreen><verb> $ ps -ax </verb></tscreen> 这会输出一大串正在执行的程序(processes)。 <item> 杀掉程序: <tscreen><verb> $ kill <PID> </verb></tscreen> 如果您不知道要如何正确的终止某一个程序,这时您可能就要手动把程序给杀死喔!... ;-). 有些时候,一个程序只能被下列一个指令杀死: <tscreen><verb> $ kill -15 <PID> $ kill -9 <PID> </verb></tscreen> </itemize> 附带一提,Sell 允许您停止或是暂时停止一个程序,将程序送到背景工作,或是将程序从背景带到前景。 在这里,程序(processes)我们称之为工作(`jobs'). <itemize> <item> 检视有多少工作(jobs)正在执行: <tscreen><verb> $ jobs </verb></tscreen> 工作(jobs)是由 Shell 给的工作号码(job number)来作区别,注意,不是 PID 喔. <item> 终止在前景工作的程序(processes): <tscreen><verb> $ CTRL-C </verb></tscreen> (不一定每一次奏效) <item> 暂停在前景工作的程序(process): <tscreen><verb> $ CTRL-Z </verb></tscreen> (同上) <item> 将暂停的程序转换成背景工作(background jobs): <tscreen><verb> $ bg <job> </verb></tscreen> <item> 将背景工作带到前景: <tscreen><verb> $ fg <job> </verb></tscreen> <item> 杀掉一个工作(job): <tscreen><verb> $ kill <%job> </verb></tscreen> </itemize> <sect1> 在访档案(files) <p> 更多有关档案的讯息。 <itemize> <item> <bf/stdin, stdout, stderr/: 在 UNIX 中,任何一个系统元件都被视为是一个档案。 指令或是应用程式读入一个所谓标准输入的档案(<tt/stdin/:通常为键盘), 输出结果到所谓标准输出的档案(<tt/stdout/ :通成为萤幕),而错误输出也是输出到一个档案, 我们称之为 <tt/stderr/ (通常也是萤幕). 使用 <tt/</ 和 <tt/>/ ,您可以将输出和输入重新导向到另外一个档案。 然而, <tt/>>/ 是将结果附加到档案的档尾,而不是覆盖原来的档案。; <tt/2>/ 重导错误讯息(stderr); 2>&1 重导错误讯息到标准输出, 而 1>&2 则是重导标准输出到错误输出。 有一个黑洞(`black hole')叫做 <tt>/dev/null</tt>: 所有导到这个档案的东西, 都将消失的无影无踪。 <item> <bf/wildcards/: 万用字元 '<tt/*/' 有相同的功能。用法: * 符合所有档案,除了隐藏档以外。 .* 符合所有隐藏档; *.* 符合只有一个点 '.' 在中间的档案。跟随著其他字元: p*r 表示 `peter' 或是 `piper' 都有可能; *c* 可能符合 `picked' 或是 `peck'。 '<tt/%/' 换成 '<tt/?/'。 还有另外一种万用字元:<tt/[]/. 用法: <tt/[abc]*/ 表示档案必须以字元 a, b, c 最为开头; <tt/*[I-N,1,2,3]/ 表示档案名称由 I, J, K, L, M, N, 1, 2, 3 作为结尾。 <item> <tt/mv/ (<tt/重新命名/) 不可以一次多个档案。即 <tt/mv *.xxx *.yyy/ 将不会执行成功; <item> 使用 <tt/cp -i/ 和 <tt/mv -i/ 可以提醒您是否要覆盖以存在的档案。 </itemize> <sect1> 列印伫列 <label id="Print Queues"> <p> 就像 VMS ,列印工作会先被放到伫列当中(queues),当您下列印指令的时候,您或许会指定列表机的名称。 例如: <tscreen><verb> $ lpr file.txt # 这将指用到预设的列表机 $ lpr -Plaser file.ps # 这将使用名为 'laser' 的列表机 </verb></tscreen> 处理列印伫列(print queues), 您可能需要下列指令: <tscreen><verb> VMS Linux ------------------------------------------------------------------------------ $ PRINT file.ps $ lpr file.ps $ PRINT/QUEUE=laser file.ps $ lpr -Plaser file.ps $ SHOW QUEUE $ lpq $ SHOW QUEUE/QUEUE=laser $ lpq -Plaser $ STOP/QUEUE $ lprm <item> </verb></tscreen> <sect> 设定 <label id="Configuring"> <p> 您的系统管理员已经提供您一些组态设定档,如: <tt/.xinitrc/, <tt/.bash_profile/, <tt/.inputrc/, 等等。 其中您想要编辑的是: <itemize> <item> <tt/ .bash_profile/ 或是 <tt/.profile/: 在 login 时,这个档案就被 Shell 给读进来了。就像 VMS 上的 <tt/LOGIN.COM/; <item> <tt/ .bash_logout/: 当要登出的时候,读取这个档案。这就像 VMS 上的 <tt/LOGOUT.COM/; <item> <tt/ .bashrc/: 被 non--login shells 读取. <item> <tt/ .inputrc/: 这个档案可以定做一组合键和设定 shell 的行为。 </itemize> 我将以我的 <tt/.bash_profile/ 最为实例。 <code> # $HOME/.bash_profile # 如果不需要,请不要重新定义 $PATH 变数。 echo $PATH | grep $LOGNAME > /dev/null if [ $? != 0 ] then export PATH="$PATH:/home/$LOGNAME/bin" # add my dir to the PATH fi export PS1='LOGNAME:\w\$ ' export PS2='Continued...>' # aliases 别名 alias bin="cd ~/bin" ; alias cp="cp -i" ; alias d="dir" alias del="delete" ; alias dir="/bin/ls $LS_OPTIONS --format=vertical" alias ed="jed" ; alias mv='mv -i' alias u="cd .." ; alias undel="undelete" # A few useful functions 一些有用的函数!酷! inst() # Install a .tar.gz archive in current directory. { gzip -dc $1 | tar xvf - } cz() # List the contents of a .zip archive. { unzip -l $* } ctgz() # List the contents of a .tar.gz archive. { for file in $* ; do gzip -dc ${file} | tar tf - done } tgz() # Create a .tgz archive a la zip. { name=$1 ; tar -cvf $1 ; shift tar -rf ${name} $* ; gzip -S .tgz ${name} } </code> 这是我的 <tt/.inputrc/: <code> # $HOME/.inputrc # 上次修改日期: 16 January 1997. # # 以下是注解,说明这个 Script 的用意。 # This file is read by bash and defines key bindings to be used by the shell; # what follows fixes the keys END, HOME, and DELETE, plus accented letters. # For more information, man readline. "\e[1~": beginning-of-line "\e[3~": delete-char "\e[4~": end-of-line set bell-style visible set meta-flag On set convert-meta Off set output-meta On set horizontal-scroll-mode On set show-all-if-ambiguous On # (F1 .. F5) are "\e[[A" ... "\e[[E" "\e[[A": "info " </code> <sect> 有用的程式 <label id="Useful Programs"> <p> <sect1> 浏览档案: <tt/less/ <p> 您将会需要每天使用这个档案浏览器。所以我将给您一些□笈让您能好好的利用这个工具。 首先,要求您的系统管理员这定 <tt/less/ 使她不只可以显示文字档,更可以压缩档案文件,等。 就像现在版本的 <tt>TYPE</tt>, <tt/less/ 可以让您浏览您目前目录下的档案。 她同时也可以接受许多额外由键盘输入的按键指令,比较有用的是: <itemize> <item> 第一, 按下 <tt/q/ 可以离开档案浏览; <item> <tt/h/ 提供您许多的线上说明; <item> <tt/g/ 跳到档头, <tt/G/ 移至档尾, 数字 n 加 <tt/g/ 表示到弟 n 行。(例如 <tt/125g/), 数字加 <tt/%/ 表示一到该档案之百分比大小的地方; <item> <tt>/pattern</tt> 向下搜寻 `pattern'; <tt/n/ 向下搜寻下笔资料; <tt>?pattern</tt> 和 <tt/N/ 表示向上寻找。 <item> <tt/m/+letter 标示目前地方 (如 <tt/ma/); <tt/'/+letter 到被标示的地方. <item> <tt/:e/ 检查新档案; <item> <tt/!command/ 执行命令列档案. </itemize> <sect1> 在 Linux 下的版本备份 <label id="Numbered Backups Under Linux"> <p> 唉, Linux 并没有提供档案版本的功能。但是您可以用两种发法解决这个问题。 第一,使用 RCS, 版本管理系统(the Revision Control System), 她可以让您管理先前的档案版本。RCS 可以在 ``The RCS MINI-HOWTO'' (<url url="http://sunsite.unc.edu/mdw/HOWTO/mini/RCS.html">) 中找到. 第二种方法,使用知道如何处理版本编号的编辑器:<tt>emacs</tt> 和 <tt>jed</tt> 都有这个功能。 在 <tt>emacs</tt>, 在 <tt>.emacs</tt> 那加入下列几行: <tscreen><verb> (setq version-control t) (setq kept-new-versions 15) ;;; or any other value (setq kept-old-versions 15) (setq backup-by-copying-when-linked t) (setq backup-by-copying-when-mismatch t) </verb></tscreen> 如果使用 <tt>jed</tt>, 请确定您的版本在 0.98.7 以上; 她的更新档,可以使其支援数字版本备份。 相关文件可以在 <tt> <url url="http://ibogeo.df.unibo.it/guido/slang/backups.sl"> </tt> 中找到. <sect1> 档案馆(Archiving): tar & gzip <p> 在 UNIX 里,有一些常用到的应用程式来集中管理及压缩档案。 <tt/tar/ 可以用来包封档案。欲包封档案可用下列指令。 <tscreen><verb> $ tar -cvf <archive_name.tar> <file> [file...] </verb></tscreen> 解开包封档案可用: <tscreen><verb> $ tar -xpvf <archive_name.tar> [file...] </verb></tscreen> 列书包封档案中所有的档案: <tscreen><verb> $ tar -tf <archive_name.tar> | less </verb></tscreen> 可以使用 <tt/compress/ 或是 <tt/gzip/ 来压缩档按以节省硬碟空间: <tscreen><verb> $ compress <file> $ gzip <file> </verb></tscreen> 如果使用 <tt/compress/ 来压缩档案,她为帮您产生副档名为 .Z 的压缩档,而 <tt/gzip/ 则是以 .gz 为副档名。 这些应用程式并不能用来包封档案,但是可以用来压缩档案。解压缩可用: <tscreen><verb> $ compress -d <file.Z> $ gzip -d <file.gz> </verb></tscreen> 详细情形,请 RMP. 此外,<tt/unarj/, <tt/zip/ 和 <tt/unzip/ 些工具也可以利用。 档案的副档名如果是 <tt/.tar.gz/ 或是 <tt/.tgz/ (表示这是一个封装档案 <tt/tar/, 然後, 使用 <tt/gzip/) 压缩软体再压缩而成的。在 UNIX 的世界,这种格式常常会会见到。 以下是示□如何察看 <tt/.tar.gz/ 档内的内容。 <tscreen><verb> $ tar -ztf <file.tar.gz> | less </verb></tscreen> 以下是示□如何解开 <tt/.tar.gz/ 档: <tscreen><verb> $ tar -zxf <file.tar.gz> </verb></tscreen> <sect> 应用 <label id="Examples"> <p> UNIX 的主要慨念是希望透过管线(piping)和重导(redirection)的观念将所有简单的指令串连起来而可以足够应付真实生活上所有复杂的工作。 让我们来看看下面的例子,我将只解释比较复杂的例子;其他简单的例子,请利用上面我所介绍的观念和说明文件(man pages),相信您一定可以很快的进入情况。 <bf/问题/: 如果只使用 <tt/ls/ 这个指令来显示档案,如果档案太多的话,常常就一飞而逝,还来不及看完,结果就被卷上去了: <bf/解决方案/: <tscreen><verb> $ ls | less </verb></tscreen> <bf/问题/: 我有一个档案,里面包含了许多文字,我想将之反向排序後列印出来: <bf/解决方案/: <tscreen><verb> $ cat myfile.txt | sort -r | lpr </verb></tscreen> <bf/问题/: 我的资料档内有许多重复的资料,我要如何删除重复的资料呢? <bf/解决方案/: <tscreen><verb> $ sort datafile.dat | uniq > newfile.dat </verb></tscreen> <bf/问题/: 我有一个叫做 'mypaper.txt' 或是 'mypaper.tex' 的档案,或是类似这样的档案名称,但是我忘记我将她们存放在什麽地方了,我要如何找到她们呢? <bf/解决方案/: <tscreen><verb> $ find ~ -name "mypaper*" </verb></tscreen> 说明: <tt/find/ 是一个非常有用的指令,她可以列出树状目录下的所有档案,(在本例中,我们是从 <tt/˜/ 这里开始寻找,也就是 $HOME 的目录)。 她的输出结果可以透过许多条件设定,而达到许多不一样的需求。例如 <tt/-name/ 。 <bf/问题/: 我想找一个档案内的某一个字,例如 'entropy',我要如何作呢?有没有类似像 <tt/SEARCH/ 这种指令呢? <bf/解决方案/: 有的, 试试看 grep 这个指令: <tscreen><verb> $ grep -l 'entropy' * </verb></tscreen> 说明:*表示所有的档案。 <bf/问题/: 在某个地方,的某个档案的内容有 'entropy' 这个字, 我想知道是哪一个档案,且放在哪里, 在 VMS 上我可以使用 <tt/search entropy [...]*.*;*/, 但是 <tt/grep/ 这个指令不可以收寻子目录,现在我要如何解决呢? <bf/解决方案/: <tscreen><verb> $ find . -exec grep -l "entropy" {} \; 2> /dev/null </verb></tscreen> 说明: <tt/find ./ 输出从目前这个目录下所有的档案(包含这个目录下所有子目录), <tt/-exec grep -l "entropy"/ 是对每一笔由 find 传出来的档案重复执行执行(represented by <tt/{}/), <tt/\/ 为结束这个指令。如果您觉得的些东西太可怕了,没错,不过您可以试著写写下面的 Script。 <code> #!/bin/sh # rgrep: recursive grep # 递回式撷取 if [ $# != 3 ] then echo "Usage: rgrep --switches 'pattern' 'directory'" exit 1 fi find $3 -name "*" -exec grep $1 $2 {} \; 2> /dev/null </code> 说明: <tt/grep/ 就像 <tt/search/, 结合了 <tt/find/ ,我们得到了两者的精华。 <bf/问题/: 我有一个资料档案,这个档案共有两列档头(header lines)(也就是说,第三笔资料才是我真正的资料), 如果我想要撷取每笔资料的第二和第五栏的资料,我需要写一个 Fortran 的程式吗? <bf/解决方案/: 不需要。来看看这个具有杀伤力的指令! <tscreen><verb> $ awk 'NL > 2 {print $2, "\t", $5}' datafile.dat > newfile.dat </verb></tscreen> 说明: <tt/awk/ 这个指令实际上可以说是一种程式语言:上面的意思是说: 在 <tt/datafile.dat/ 这个档案里,从档案的第三行开始的每一行,印出每一行的第二和第五栏位, 以 tab 为分隔符号。学会了 <tt/awk/ 一定会让您事半功倍的。 <bf/问题/: 我从 FTP 站下载了 <tt/ls-lR.gz/ 这个档案,想要察看档案内容。 对每一个子目录而言,她有一行写说 "total xxxx", 其中 xxxx 表示档案大小(kbytes) 我想知道所有 xxxx 值的总和,我要如何作呢? <bf/解决方案/: <tscreen><verb> $ zcat ls-lR.gz | awk ' $1 == "total" { i += $2 } END {print i}' </verb></tscreen> 说明: <tt/zcat/ 可以列出 <tt/.gz/ 的档案内容。然後将 zcat 得到的结果转送(pipe)到 <tt/awk/。看到了吧!了解 awk 真的对您有很大的帮助喔。RMP! <bf/问题/: 我已经写了一只 <tt/myprog/ 的 Fortran 的程式,可以计算由命令列传进来的档案的资料, 可是,我有很多个资料档需要输入到这只程式,每一个档案将会有一个结果档案。但是每次都要输入档名实在很烦人, 在 VMS 上,我需要写一个罗唆的命令档(command file)才可以解决,那麽在 Linux 上呢? <bf/解决方案/: 只要一个小小的 Script 就可以解决了。修改您的程式,让您的程式可以预定读入 '<tt/mydata.dat/' 这个档案, 将结果输出到萤幕(stdout), 然後编辑下面的 Script: <code> #!/bin/sh # myprog.sh: run the same command on many different files # usage: myprog.sh *.dat for file in $* # for all parameters (e.g. *.dat) do # append the file name to result.dat echo -n "${file}: " >> results.dat # copy current argument to mydata.dat, run myprog # and append the output to results.dat cp ${file} mydata.dat ; myprog >> results.dat done </code> <bf/问题/: 我希望将所有档案内的 `geology' 字替换成 `geophysics' ,我需要手动编辑吗?! <bf/解决方案/: 不需要。 下面的 Shell Script 可以帮您办到: <code> #!/bin/sh # replace $1 with $2 in $* # usage: replace "old-pattern" "new-pattern" file [file...] OLD=$1 # first parameter of the script NEW=$2 # second parameter shift ; shift # discard the first 2 parameters: the next are the file names for file in $* # for all files given as parameters do # replace every occurrence of OLD with NEW, save on a temporary file sed "s/$OLD/$NEW/g" ${file} > ${file}.new # rename the temporary file as the original file /bin/mv ${file}.new ${file} done </code> <bf/问题/: 我有一些档案,我不知道她们的档案长度,我必须移除这些档案内的倒数第二和倒数第三行,需要手动吗? <bf/解决方案/: 当然不需要,还是使用 Shell Script: <code> #!/bin/sh # prune.sh: removes n-1th and n-2th lines from files # usage: prune.sh file [file...] for file in $* # for every parameter do LINES=`wc -l $file | awk '{print $1}'` # 计算总共有几行 LINES=`expr $LINES - 3` # LINES = LINES - 3 head -n $LINES $file > $file.new # 输出前 LINES 行 tail -n 1 $file >> $file.new # 再将最後一行附加到档案最後 done </code> 希望以上这些实例增加您不少的食欲... <sect> 不可少的小偏方 <p> <itemize> <item> <bf/Command completion/: 当您在命令列欲输入某一指令的时候,您不需要完全输入这个指令的所有名称, 输入前几个字元後,再按 <TAB> ,系统会帮您完成输入所有的指令名称; 例如: 您必须输入 <tt>less this_is_a_long_name</tt>; 现在您只要输入 <tt>less thi<TAB></tt> 系统就会帮您输入剩下的部份,不需要再书如全部的档名了。 (如果您有很多档案都是以这些字元作开头,当然系统就会显示出所有以这几个字元开头的档案,但是,您可以输入足够的字元,就可以得到您需要的唯一档案。) <item> <bf/Back-scrolling/: 同时按 SHIFT--PAG UP 可以让您的萤幕往回卷到以前显示过的, 但是可以往回卷几页,则需要视您的显示卡的记忆体而定了。 <item> <bf/Resetting the screen/: 不果您不小心用 <tt/more/ 或 <tt/cat/ 开启了一个二进位档(binary file), 那您的萤幕可能为因此而乱掉。这时候您可以使用 <tt/reset/ 或是使用 <tt/echo CTRL-V ESC c RETURN/ 可以让您的萤幕恢复正常。 <item> <bf/Pasting text/: 在 X 下,以滑鼠在 <tt/xterm/ 视窗拖曳出一个区域, 然後按滑鼠中键(如果您的滑鼠没有中键,可以同时按滑鼠的左右键模拟中键)就可以贴上您复制的文字。 <item> <bf/Using the mouse/: 在终端机模式下,您可能需要寻为您的系统管理员有没有安装 <tt/gpm/ 这只程式, 如果有,您就可以用滑鼠拖曳出一个区域,然後按滑鼠的左键,就可以贴上您刚刚拖曳出来的文字区域。 (不同的虚拟终端机(VC)可能会有不一样的操作方式)。 </itemize> <sect> 在 Linux 上读取 VMS 的磁带 <p> (以下这段是由 Mike Miller 先生所著) <sect1> 简介 <p> 有时候您可能需要读由 VMS 做出来的磁带(或是为了让 VMS 的机器和 *nix 系统可以读取的磁带), 大致上,对 DECFILES11A 磁带并不会太难。 或许您曾读过 Linux 的 mini-HOWTO, 但是,我相信,我在这里提及的一些观念也是和任何一种 *nix 系统。 我曾经在 Linux, HP, Sun and DEC *nix 等系统中试过。比较不一样的地方是,每种作业系统对装置名称(device names)可能会有所不同, 而 mt 在指明装置名称(device name)的时候,其选项(options)也可能因作业系统而异。 例如:在 Linux 上是 mt -f ,但是在 HPUX 9 上却是 mt -t。 注意 - 我只以 Exabyte 8mm SCSI tape drives 实作过,如果您已经读过其他的格式, 请让我知道,我将会把她增加到这份 Note 中。 <sect1> 一些基本常识 <p> 当读取 VMS 由 ``copy'' 指令作成的磁带时,(或是看起来像是由 copy 指令作成的磁带), 您必须要知道,每个实际的档案将会分成三的档案存放在磁带上,分别是“档头(header)”, “资料(data)”, 和“档尾(trailer)”。 其中档头(header) 和 档尾(trailer)存放著档案的讯息,和在 VMS 上的位置。而资料(data)当然就是存放原来的资料啦! 这些档案都可以由 dd 这个指令从磁带(tape)上萃取出来。 由 mt 指令,可以将磁带转到所需要的位置。 □例:我有一个连续存放著档案的磁带。最前面两个在 VMS 上的档名为 ce66-2.evt 和 ce66-3.evt 磁带的标签(label)是 c66a2。 如果我执行下列指令: <tscreen><verb> > dd if=$TAPE bs=16k of=header1 > dd if=$TAPE bs=16k of=data1 > dd if=$TAPE bs=16k of=trailer1 > dd if=$TAPE bs=16k of=header2 > dd if=$TAPE bs=16k of=data2 > dd if=$TAPE bs=16k of=trailer2 </verb></tscreen> 我 dd 了六个档案:header1, data1, trailer1, header2, data2 和 trailer2. 使用语法如下:if="input file", bs="block size" 和 of="output file". TAPE 这个便是须视您的机器上的装置名称而定,例如:如果您在 Linux 上使用 SCSI 的磁带装置, 您的装置名称可能是 /dev/nts0 。 如果您想要读第二个档案,不是第一个。您不在意档头(header),而且您想要使用原来的档名,您可以这麽作: <tscreen><verb> > mt -f $TAPE fsf 4 > dd if=$TAPE bs=16k of=ce66-2.evt > mt -f $TAPE fsf 1 </verb></tscreen> 注意 “4” - 跳过第一个档案所附属的三个档案,所以下一比(第二笔)的档头将会是从第四笔开始。 第二个 mt 为跳过第二笔档案的档尾(tailer)并且指到下一笔档案(第三笔资料的档头)。 当然,您也可以使用 mt 使磁带快转(bsf), 倒转(rewind),或是 磁头归位(offline, rewoffl). <sect1> 更多细节 <p> 档头(header) 和 档尾(trailer) 包含了给 VMS 储存档案的一些讯息,例如区块大小(block size)。 同时她们也包含了档案名称,方便您建立 Script 档来自动读取档案或是搜寻特定的档案。 然而,在磁带上的第一个档头档(header file),和其他磁带上的档头档有些许的差异。 对於在磁带上的第一个档案(假设为 header1),最前面的四个字元将会是 "VOL1" ,其後伴随著版本名称(volume name)。 本例中,header1 的最初内容应该是 "VOL1C66A2"。随後是一个字串"HDR1" ,表示这是一个档头档(header file)。 然後才是档案名称(file name)。本例中,她会是 "HDR1CE66-2.EVT"。下一个栏位又是版本名称(volume name)。 对於其他的不是磁带上第一个档头档的档头档,最初的 VOL1 栏位将不会存在。 其他的栏位就和前面所介绍的第一个档头档的结构一模一样。另一个比较有用的栏位是第七个栏位。 她是以 "DECFILES11A" 为结尾。她必须存在,用还确认 DEC Files11A standard. <tscreen><verb> field initial header subsequent headers ===== ============= ================== 1 VOL1 + volume name HDR1 + file name 2 3HDR1 + file name volume name 3 volume name 6 ...DECFILES11A 7 ...DECFILES11A </verb></tscreen> 其他更详细的档头和档尾的结构,请参考 DEC FILES11A 的说明文件。 (on the orange/grey wall - ask your local VMS folks :-). <sect1> 区块大小的建议(Block Size) <p> 在例子中,我使用的区块大小是 16K。在 *nix 系统上,磁碟上的档案并没有和区块大小有关连, 然而,在 VMS 上,每一个档案都有一个明确的区块大小(block size)。也就是说,在 Linux 端, 区块大小并没多太大的关系,除非当不容易从磁带中读出档案的时候。如果您找不到区块大小(block size), 您可以试著在磁碟装置上,用 `mt -f $TAPE setblk 0' 来设定硬体的区块大小。 用 setblk 选项的萃取的形式可能会随著 mt 的版本不同而有所不一样, 您的磁带装置的硬体界面,还有您喜爱的 *nix 系统也想相当的关系。 (感谢 Wojtek Skulski (<url url="skulski@nsrlc6.nsrl.rochester.edu">) 提出 setblk 相关部份.) <sect> 总结 <p> <sect1> 版权 <p> 除非有特别声明,Linux HowTo 文件的版权归於个别(原)作者所有。 只要这份版权声明保留在所有的文件中,Linux HowTo 文件可以全部或部份地以任何形式的媒体修改或散播。 甚至允许有营利性质的行为。然而,希望能先知会原作者相关文件的散布。 任何的翻译,引用,或是整合的作品,凡包含到 Linux HowTo 文件者,都属於这份版权声明的□围。 也就是说,您不允许从 HOWTO 中发表衍生作品,或是增加额外的限制。 但在某些假定的情况下,这些规定可以有例外。相关细节请联系 Linux HOWTO 的协调人。 连络方式可在下文中找到。 总之,我们希望尽可能的透过任何形式的管道提升这份文件的宣传。但是我们希望能够保留这份版权声明。 并且如有任何的修改,我们将会很乐以的被告知。 如果您有任何的疑问,请连联系 Linux HOWTO 的协调者 Tim Bynum, 您可以使用 email: <url url="linux-howto@sunsite.unc.edu"> 与其联系。 <sect1> 後序 <p> 这份作品是我在 Settore di Geofisica of the Universita' di Bologna (Italy) 的实作经验。 其 VAX 4000 也已经被以 Linux 为作业系统的奔腾(pentium)的个人电脑所代替了。 我大部分的同事以前都是 VMS 的爱用者,可是现在她们都已经转换到 Linux 上了。 ``From VMS to Linux HOWTO''(从 VMS 到 Linux)这份文件主要是由 Guido Gonzato 所撰写的, <url url="guido ``at'' ibogeo.df.unibo.it">, Mike Miller 先生, <url url="miller5@uiuc.edu">, 他贡献如何从 Linux 上读取 VMS 的备份磁带这一部份文章。 十分感谢我的同事和朋友们,他们帮我解释了大部分 VMS 使用者的需要和习惯,尤其感谢 Dr. Warner Marzocchi。 请帮我改善这份 HOWTO 文件。因为我不是 VMS 专家,而且也不可能是,所以十分欢迎您的建议,和错误回报。 欢迎您进入 Linux 的殿堂, Guido <tt/=8-)/ <sect1> 译者序 <p> 在翻译这篇文章的时候,我边翻译边想,台湾现在还有人在使用 VMS 吗? 甚至还不是很多人知道 VMS呢!当我翻译完後发现,其实这篇文章不只适合 VMS 的使用者, 任何想要进入 Linux 世界的人都可以参考看看,因为,这篇文章的观念还不算太难, 读完後,大致上可以了解 Linux 的基本操作。(甚是您可以把他想像成从 dos 到 Linux)。 但是,说真的,光凭这篇文章还是不够的,我想,如果 Linux 的路要走得平顺一点的话, 买一本好书绝对是必要的。 或许,有些地方翻的不是很贴切,如果有好的建议,或是有任何地方的误谬, 请不吝赐教!Linux 的世界,是一个随时随地都在学习的世界! Linux 爱好者, 峰舟 email: <url url="sonnystone@kimo.com.tw"> <p> Dec 27, 2000 于 MI。 </article>