学习 bash shell
本文数据主要针对 Fedora Core 4 的系统进行说明, Fedora Core 1 主要是由 Red Hat Linux 9 改版而来, 这个 Red Hat Linux 9 并不是当前大家听到的 RHEL 喔!那是在 RHEL 出现之前的产品,基本上是在 2003 年以前的作品了!Fedora Core 4 则是在 2005 年 6 月份发布,使用的内核是 2.6.11 版,当时是很红的一个作品!只是生命周期太短,所以用这个 Fedora 系列来介绍 Server, 当时的决定确实有点莫名其妙了...
建议您前往本站查找最新版本的 Linux distribution 文章来阅读,比较不会浪费时间。那为何还需要编辑 Fedora Core 4 的数据呢? 鸟哥只想要做个自己曾经撰写过的文档内容保存而已啰! ^_^!最新文章请前往鸟站首页查阅啰!
文本模式 (command line) 这种指令下达的方式,在 Linux 里面,其实就相当于是 bash 的工具与接口! 因为 Linux 就是以 bash 为缺省的 shell 的!那么前几章我们都已经很快乐的进行了很多的指令下达啰~ 所以说, bash shell 根本就不难吧~是啦!只要能够熟悉的话,那么确实他也不是这么不可亲近的一项工具啊~ 这个章节中,鸟哥会由变量谈起,先讲到环境变量的功能与修改的问题, 然后会继续提到历史指令的运用。接下来,就会谈一下『数据流重导向』这个重要概念, 最后就是管线命令的利用啦!好好清一清脑门,准备用功去啰~ ^_^ 这个章节几乎是所有 command line 与未来主机维护与管理的重要基础,一定要好好仔细的阅读喔!
[root@linux ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin .....(中间省略).....如上所示,在每一行的最后一个数据,就是您登录后,可以取得的缺省的 shell 啦! 那你也会看到, root 是 /bin/bash ,不过,系统帐号 bin 与 daemon 等等,就使用那个怪怪的 /sbin/nologin 啰~关于用户这部分的内容,我们留在 帐号管理 时提供更多的说明。
[root@linux ~]# type [-tpa] name 参数: :不加任何参数时,则 type 会显示出那个 name 是外部指令还是 bash 内置的指令! -t :当加入 -t 参数时,type 会将 name 以底下这些字眼显示出他的意义: file :表示为外部指令; alias :表示该指令为命令别名所设置的名称; builtin :表示该指令为 bash 内置的指令功能; -p :如果后面接的 name 为指令时,会显示完整文件名(外部指令)或显示为内置指令; -a :会将由 PATH 变量定义的路径中,将所有含有 name 的指令都列出来,包含 alias 范例: 范例一:查找一下 ls 这个指令是否为 bash 内置? [root@linux ~]# type ls ls is aliased to `ls --color=tty' # 没有加上任何参数,仅列出 ls 这个指令的最主要使用情况 [root@linux ~]# type -t ls alias # -t 参数则仅列出 ls 这个指令的最主要使用情况说明 [root@linux ~]# type -a ls ls is aliased to `ls --color=tty' ls is /bin/ls # 利用所有方法找出来的 ls 相关信息都会被列出来! 范例二:那么 cd 呢? [root@linux ~]# type cd cd is a shell builtin通过 type 这个指令的用途,我们可以知道每个指令是否为 bash 的内置指令。 此外,由于利用 type 搜索后面的名称时,如果后面接的名称并不能以运行档的状态被找到, 那么该名称是不会被显示出来的。举例来说,您的 FC4 应该不会有 vbird 这个指令吧?! 输入 type -p vbird 看一下,果然没有输出任何数据!而如果您输入的是 type -p touch 呢? 则会出现 /bin/touch !呵呵!所以,这个 type 也可以用来作为类似 which 指令的用途啦!找指令用的!
[root@linux ~]# command [-options] parameter1 parameter2 ... 指令 选项 参数(1) 参数(2) 说明: 0. 一行指令中第一个输入的绝对是『指令(command)』或『可运行文件』 1. command 为指令的名称,例如变换路径的指令为 cd 等等; 2. 中刮号[]并不存在于实际的指令中,而加入参数设置时,通常为 - 号,例如 -h; 有时候完整参数名称会输入 -- 符号,例如 --help; 3. parameter1 parameter2.. 为依附在 option 后面的参数, 或者是 command 的参数; 4. command, -options, parameter1.. 这几个咚咚中间以空格来区分, 不论空几格 shell 都视为一格; 5. 按下 [Enter] 按键后,该指令就立即运行。[Enter] 按键为 <CR> 字符, 他代表着一行指令的开始启动。 6. 指令太长的时候,可以使用 \ 符号来跳脱 [Enter] 符号, 使指令连续到下一行。注意! \ 后就立刻接特殊字符。 7. 在 Linux 系统中,英文大小写字母是不一样的。举例来说, cd 与 CD 并不同。 范例: 范例一:列出 /root 底下的各文件名称 [root@linux ~]# ls -al /root [root@linux ~]# ls -al /root # 不论指令与参数中间空几格,都是可以接受的! 范例二:如果指令太长的话,如何使用两行来输出? [root@linux ~]# cp /var/spool/mail/root /etc/crontab \ > /etc/fstab /root # 上面这个指令,就是将三个文件拷贝到 /root 这个目录下而已。不过,因为指令太长, # 于是鸟哥就利用 \[Enter] 来将 [Enter] 这个按键『跳脱!』开来,让 # [Enter] 按键不再具有上述说明的第 5 点功能!好让指令继续在下一行输入。 # 需要特别留意, [Enter] 按键是紧接着反斜线 (\) 的,两者中间没有其他字符。 # 因为 \ 仅跳脱『紧接着的下一个字符』而已!所以,万一我写成: # \ [Enter] ,亦即 [Enter] 与反斜线中间有一个空格时,则 \ 跳脱的是『空白键』 # 而不是 [Enter] 按键!这个地方请在仔细的看一遍!很重要! # 如果顺利跳脱 [Enter] 后,下一行最前面就会主动出现 > 的符号, # 您可以继续输入指令啰!也就是说,那个 > 是系统自动出现的,你不需要输入。总之,当我们顺利的在终端机 (tty) 上面登录后, Linux 就会依据 /etc/passwd 文件的设置给我们一个 shell ,缺省就是 bash ,然后我们就可以依据上面的指令下达方式来操作 shell, 之后,我们就可以通过 man 这个在线查找来查找指令的使用方式与参数说明, 很不错吧!那么我们就赶紧更进一步来操作 bash 这个好玩的东西啰!
[root@linux ~]# echo $variable [root@linux ~]# echo $PATH /bin:/sbin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin [root@linux ~]# echo ${PATH}变量的取用就如同上面的范例,利用 ehco 就能够读出,只是需要在变量名称前面加上 $ , 或者是以 ${variable} 的方式来取用都可以!当然啦,那个 echo 的功能可是很多的, 我们这里单纯是拿 echo 来读出变量的内容而已,更多的 echo 使用,请自行给他 man echo 吧! ^_^
例题一:请在屏幕上面显示出您的环境变量 HOME 与 MAIL: 答:
echo $MAIL |
[root@linux ~]# echo $myname <==这里并没有任何数据~因为这个变量尚未被设置!是空的! [root@linux ~]# myname=VBird [root@linux ~]# echo $myname VBird <==出现了!因为这个变量已经被设置了!瞧!如此一来,这个变量名称 myname 的内容就带有 VBird 这个数据啰~ 而由上面的例子当中,我们也可以知道: 当一个变量名称尚未被设置时,缺省的内容是『空』的。 另外,变量在设置时,还是需要符合某些规定的,否则会设置失败喔! 这些规则如下所示啊!
范例一:设置一变量 name ,且内容为 VBird 。 [root@linux ~]# 12name=VBird -bash: 12name=VBird: command not found <==屏幕会显示错误!因为不能以数字开头! [root@linux ~]# name = VBird <==还是错误!因为有空白! [root@linux ~]# name=VBird <==OK 的啦! 范例二:承上题,若变量内容为 VBird's name 呢? [root@linux ~]# name=VBird's name # 因为单引号可以将 Enter 这个特殊字符取消,所以,您可以继续在下一行输入内容~ # 不过,这与我们要达到的功能不同,所以,算是失败的啦! [root@linux ~]# name="VBird's name" <==OK 的啦! [root@linux ~]# name=VBird\'s\ name # 利用反斜线 (\) 跳脱特殊字符,例如单引号与空白键,这也是 OK 的啦! 范例三:我要在 PATH 这个变量当中『累加』:/home/dmtsai/bin 这个目录 [root@linux ~]# PATH=$PATH:/home/dmtsai/bin [root@linux ~]# PATH="$PATH":/home/dmtsai/bin # 上面这两种格式在 PATH 里头的设置都是 OK 的!但是底下的例子就不见得啰! 范例四:呈范例三,我要将 name 的内容多出 "yes" 呢? [root@linux ~]# name=$nameyes # 知道了吧?如果没有双引号,那么变量成了啥?name 的内容是 $nameyes 这个变量! # 呵呵!我们可没有设置过 nameyes 这个变量呐!所以,应该是底下这样才对! [root@linux ~]# name="$name"yes [root@linux ~]# name=${name}yes 范例五:如何让我刚刚设置的 name=VBird 可以用在下个 shell 的进程? [root@linux ~]# name=VBird [root@linux ~]# bash <==进入到所谓的子进程 [root@linux ~]# echo $name <==嘿嘿!并没有刚刚设置的内容喔! [root@linux ~]# exit <==离开刚刚的子进程 [root@linux ~]# export name [root@linux ~]# bash <==进入到所谓的子进程 [root@linux ~]# echo $name <==出现了设置值了! [root@linux ~]# exit <==离开刚刚的子进程 # 什么是『子进程』呢?就是说,在我目前这个 shell 的情况下, # 去激活另一个新的 shell ,新的那个 shell 就是子进程啦!在一般的状态下, # 父进程的自订变量是无法在子进程内使用的。但是通过 export 将变量变成 # 环境变量后,就能够在子进程底下应用了!很不赖吧!至于进程的相关概念, # 我们会在『进程与资源管理』章节当中提到的喔! 范例六:如何进入到您目前内核的模块目录? [root@linux ~]# cd /lib/modules/`uname -r`/kernel # 每个操作系统内核版本都不相同,以 FC4 为例,他的缺省内核版本是 # 2.6.11-1.1369_FC4 所以,他的模块目录在 /lib/modules/2.6.11-1.1369_FC4/kernel 。 # 因为每个 distributions 的这个值都不相同,但是我们却可以利用 uname -r 这个指令 # 先取得版本信息,所以啰,就可以通过上面指令当中的内含指令 `uname -r` # 先取得版本输出到 cd .. 那个指令当中,就能够顺利的进入目前内核的驱动程序所放置 # 的目录啰!很方便吧! 范例七:取消刚刚设置的 name 这个变量内容 [root@linux ~]# unset name根据上面的案例你可以试试看!就可以了解变量的设置啰!这个是很重要的呦!请勤加练习!! 其中,较为重要的一些特殊符号的使用啰!例如单引号、双引号、转义字符、钱字号、quote 符号等等,底下的例题想一想吧!
例题二:在变量的设置当中,单引号与双引号的用途有何不同? 答:
[root@linux ~]# name=VBird [root@linux ~]# echo $name VBird [root@linux ~]# myname="$name its me" [root@linux ~]# echo $myname VBird its me [root@linux ~]# myname='$name its me' [root@linux ~]# echo $myname $name its me 发现了吗?没错!使用了单引号的时候,那么 $name 将失去原有的变量内容, 仅为一般字符的显示型态而已!这里必需要特别小心在意! |
例题三:在指令下达的过程中, quote ( ` ) 这个符号代表的意义为何? 答:
另外再举个例子,我们也知道, locate 指令可以列出所有的相关文件文件名,但是, 如果我想要知道各个文件的权限呢?举例来说,我想要知道每个 crontab 相关文件名的权限: [root@linux ~]# ls -l `locate crontab` 如此一来,先以 locate 将文件名数据都列出来,再以 ls 指令来处理的意思啦!瞭了吗? ^_^ |
范例一:列出目前的 shell 环境下的所有环境变量与其内容。 [root@linux ~]# env HOSTNAME=linux.dmtsai.tw <== 这部主机的主机名称 SHELL=/bin/bash <== 目前这个环境下,使用的 Shell 是哪一个程序? TERM=xterm <== 这个终端机使用的环境是什么类型 HISTSIZE=1000 <== 这个就是『记录指令的笔数』在 FC4 缺省可记录 1000 笔 USER=root <== 用户的名称啊! LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01: or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=0 0;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz= 00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;3 1:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00 ;35:*.xpm=00;35:*.png=00;35:*.tif=00;35: <== 一些颜色显示 ENV=/root/.bashrc <== 使用的个人环境设置档 MAIL=/var/spool/mail/root <== 这个用户所取用的 mailbox 位置 PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin: /root/bin <== 不再多讲啊!是运行档指令搜索路径 INPUTRC=/etc/inputrc <== 与键盘按键功能有关。可以设置特殊按键! PWD=/root <== 目前用户所在的工作目录 (利用 pwd 取出!) LANG=en_US.UTF-8 <== 这个与语系有关,底下会再介绍! HOME=/root <== 这个用户的家目录啊! _=/bin/env <== 上一次使用的指令的最后一个参数(或指令本身)env 是 environment (环境) 的简写啊~ 上面的例子当中,是列出来所有的环境变量。当然,如果使用 export 也会是一样的内容~ 只不过, export 还有其他额外的功能就是了,我们等一下再提这个 export 指令。 那么上面这些变量有些什么功用呢?底下我们就一个一个来分析分析!
[root@linux ~]# declare -i number=$RANDOM*10/32767 ; echo $number 8 <== 此时会随机取出 0~9 之间的数值喔!
[root@linux ~]# set BASH=/bin/bash <== bash 的主程序放置路径 BASH_VERSINFO=([0]="3" [1]="00" [2]="16" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu") <== bash 的版本啊! BASH_VERSION='3.00.16(1)-release' <== bash 的版本啊! COLORS=/etc/DIR_COLORS.xterm <== 使用的颜色纪录文件 COLUMNS=115 <== 在目前的终端机环境下,使用的字段有几个字符长度 HISTFILE=/root/.bash_history <== 历史命令记录的放置文件,隐藏档 HISTFILESIZE=1000 <== 存起来(与上个变量有关)的文件之指令的最大纪录笔数。 HISTSIZE=1000 <== 目前环境下,可记录的历史命令最大笔数。 HOSTTYPE=i386 <== 主机安装的软件主要类型。我们用的是 i386 兼容机器软件 IFS=$' \t\n' <== 缺省的分隔符号 LINES=35 <== 目前的终端机下的最大行数 MACHTYPE=i386-redhat-linux-gnu <== 安装的机器类型 MAILCHECK=60 <== 与邮件有关。每 60 秒去扫瞄一次信箱有无新信! OLDPWD=/home <== 上个工作目录。我们可以用 cd - 来取用这个变量。 OSTYPE=linux-gnu <== 操作系统的类型! PPID=20046 <== 父进程的 PID (会在后续章节才介绍) PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\007"' <== 上面这个是命令提示字符!与底下也有关。 PS1='[\u@\h \W]\$ ' <== PS1 就厉害了。这个是命令提示字符,也就是我们常见的 [root@linux ~]# 或 [dmtsai ~]$ 的设置值啦!可以更动的! RANDOM=13586 <== 乱数啊!上面已经提过啰~ SUPPORTED=zh_TW.UTF-8:zh_TW:zh:en_US.UTF-8 <== 本系统所支持的语系 name=VBird <== 刚刚设置的自订变量也可以被列出来喔! $ <== 目前这个 shell 所使用的 PID ? <== 刚刚运行完指令的回传值。一般来说,不论是否为环境变量,只要跟我们目前这个 shell 的操作接口有关的变量, 通常都会被设置为大写字符,也就是说,『基本上,在 Linux 缺省的情况中,使用{大写的字母}来设置的变量一般为系统内定需要的变量』。
[root@linux home]# PS1='[\u@\h \w \A #\#]\$ ' [root@linux /home 17:02 #85]# # 看到了吗?提示字符变了!变的很有趣吧!其中,那个 #85 比较有趣, # 如果您按下 [Enter] 后,该数字就会增加喔!为啥?上面有说明ㄇㄟ!
[root@linux ~]# echo $SHELL /bin/bash [root@linux ~]# echo $? 0 # 因为上个指令运行过程中,并没有错误,为成功的运行完毕,所以回传 0 。 [root@linux ~]# 12name=VBird -bash: 12name=VBird: command not found [root@linux ~]# echo $? 127 # 发生错误啦!所以 echo $? 时,就会出现错误的代码! # 我们可以利用这个代码来搜索错误的原因喔! [root@linux ~]# echo $? 0 # 咦!怎么又变成正确了?这是因为 "?" 只与『上一个运行指令』有关, # 所以,我们上一个指令是运行『 echo $? 』,当然没有错误,所以是 0 没错!
[root@linux ~]# export declare -x ENV="/root/.bashrc" declare -x HISTSIZE="1000" declare -x HOME="/root" declare -x HOSTNAME="linux.dmtsai.tw" declare -x INPUTRC="/etc/inputrc" declare -x LANG="en_US.UTF-8" declare -x MAIL="/var/spool/mail/root" declare -x SHELL="/bin/bash" # 很多都直接省略了!不然....重复性太高,浪费版面~ ^_^
[root@linux ~]# locale -a aa_DJ aa_DJ.iso88591 en_US en_US.iso88591 en_US.iso885915 en_US.utf8 zh_TW zh_TW.big5 zh_TW.euctw zh_TW.utf8 # 其实输出的内容有很多,鸟哥将一些信息舍弃了~ # 从上面的输出中,我们也不难看出,系统是有支持 big5, utf8 等中文语系数据的!中文语系至少支持了两种以上的编码,一种是目前还是很常见的 big5 ,另一种则是越来越热门的 utf-8 编码。 那么我们如何修订这些编码呢?其实可以通过底下这些变量的说:
[root@linux ~]# LANG <==主语言的环境 [root@linux ~]# LC_CTYPE <==字符辨识的编码 [root@linux ~]# LC_NUMERIC <==数字系统的显示消息 [root@linux ~]# LC_TIME <==时间系统的显示数据 [root@linux ~]# LC_COLLATE <==字符串的比较与排序等 [root@linux ~]# LC_MONETARY <==币值格式的显示等 [root@linux ~]# LC_MESSAGES <==消息显示的内容,如功能表、错误消息等 [root@linux ~]# LC_ALL <==语言环境的整体设置。基本上,你可以逐一设置每个与语系有关的变量数据,但事实上,如果其他的语系变量都未设置, 且您有设置 LANG 或者是 LC_ALL 时,则其他的语系变量就会被这两个变量所取代! 这也是为什么我们在 FC4 当中,通常仅设置 LANG 这个变量而已!因为他是最主要的设置变量。 好了,那么你应该要觉得奇怪的是,为什么在 Linux 主机的终端机接口 (tty1 ~ tty6) 的环境下,如果 LANG=zh_TW.big5 这个设置值生效后,使用 man 或者其他消息输出时, 都会有一堆乱码,尤其是使用 ls -l 这个参数时?
[root@linux ~]# vi /etc/sysconfig/i18n
LANG="en_US.UTF-8"
SYSFONT="latarcyrheb-sun16"
SUPPORTED="zh_TW.UTF-8:zh_TW:zh:en_US.UTF-8"
你可以在这个文件当中加入 LC_TIME 或者其他语系相关变量的设置内容,
也可以直接修改 LANG 那个变量即可啊! ^_^ 但,事实上,我们还可以通过个人的环境设置档来设置 LANG 呢!
如此一来,则不必修订系统的语系文件,比较安全啦![root@linux ~]# read [-pt] variable 参数: -p :后面可以接提示字符! -t :后面可以接等待的『秒数!』这个比较有趣~不会一直等待用户啦! 范例: 范例一:让用户由键盘输入一内容,将该内容变成 atest 变量 [root@linux ~]# read atest This is a test [root@linux ~]# echo $atest This is a test 范例二:提示用户 30 秒内输入自己的大名,将该输入字符串做成 named 变量 [root@linux ~]# read -p "Please keyin your name: " -t 30 named Please keyin your name: VBird Tsai [root@linux ~]# echo $named VBird Tsairead 之后不加任何参数,直接加上变量名称,那么底下就会主动出现一个空白行,等待您输入。 如果加上 -t 后面接秒数之后,例如上面的范例当中,那么 30 秒之内没有任何动作时, 该指令就会自动略过了~如果是加上 -p ,嘿嘿!后面就会有比较多可以用的提示字符给我们参考! 在指令的下达里面,比较美观啦! ^_^
[root@linux ~]# declare [-aixr] variable 参数: -a :将后面的 variable 定义成为数组 (array) -i :将后面接的 variable 定义成为整数数字 (integer) -x :用法与 export 一样,就是将后面的 variable 变成环境变量; -r :将一个 variable 的变量设置成为 readonly ,该变量不可被更改内容,也不能 unset 范例: 范例一:让变量 sum 进行 100+300+50 的加总结果 [root@linux ~]# sum=100+300+50 [root@linux ~]# echo $sum 100+300+50 <==咦!怎么没有帮我计算加总?因为这是文本型态的变量属性啊! [root@linux ~]# declare -i sum=100+300+50 [root@linux ~]# echo $sum 450 <==瞭乎?? 范例二:将 sum 变成环境变量 [root@linux ~]# declare -x sum 范例三:让 sum 变成唯读属性,不可更动! [root@linux ~]# declare -r sum [root@linux ~]# sum=tesgting -bash: sum: readonly variable <==老天爷~不能改这个变量了!declare 也是个很有用的功能~尤其是当我们需要使用到底下的数组功能时, 他也可以帮我们声明数组的属性喔!不过,老话一句,数组也是在 shell script 比较常用的啦!
范例:设置上面提到的 var[1] ~ var[3] 的变量。 [root@linux ~]# var[1]="small min" [root@linux ~]# var[2]="big min" [root@linux ~]# var[3]="nice min" [root@linux ~]# echo "${var[1]}, ${var[2]}, ${var[3]}"比较有趣的地方在于『读取』,一般来说,建议直接以 ${数组} 的方式来读取, 比较正确无误的啦!
[root@linux ~]# ulimit [-SHacdflmnpstuv] [配额] 参数: -H :hard limit ,严格的设置,必定不能超过设置的值; -S :soft limit ,警告的设置,可以超过这个设置值,但是会有警告消息, 并且,还是无法超过 hard limit 的喔!也就是说,假设我的 soft limit 为 80 , hard limit 为 100 ,那么我的某个资源可以用到 90 , 可以超过 80 ,还是无法超过 100 ,而且在 80~90 之间,会有警告消息的意思。 -a :列出所有的限制额度; -c :可创建的最大内核文件容量 (core files) -d :进程数据可使用的最大容量 -f :此 shell 可以创建的最大文件容量 (一般可能设置为 2GB)单位为 Kbytes -l :可用于锁定 (lock) 的内存量 -p :可用以管线处理 (pipe) 的数量 -t :可使用的最大 CPU 时间 (单位为秒) -u :单一用户可以使用的最大进程(process)数量。 范例: 范例一:列出所有的限制数据 [root@linux ~]# ulimit -a 范例二:限制用户仅能创建 1MBytes 以下的容量的文件 [root@linux ~]# ulimit -f 1024还记得我们在 Linux 磁盘文件系统 里面提到过,单一 filesystem 能够支持的单一文件大小与 block 的大小有关。例如 block size 为 1024 byte 时,单一文件可达 16GB 的容量。但是,我们可以用 ulimit 来限制用户可以创建的文件大小喔! 利用 ulimit -f 就可以来设置了!例如上面的范例二,要注意单位喔!单位是 Kbytes。 若改天你一直无法创建一个大容量的文件,记得瞧一瞧 ulimit 的信息喔!( 不过,要注意的是,一般身份用户如果以 ulimit 设置了 -f 的文件大小, 那么他『只能减小文件大小,不能增加文件大小喔!』)
[root@linux ~]# echo $HOME [root@linux ~]# echo ${HOME}那么,在那个 ${variable} 的使用方法中,其实,我们还可以将变量进行一些修订的工作喔! 只要加上一些字符标志,后面再接着使用比对字符串,就能够修改变量的内容了! 我们取底下的例子来说明:在底下的例子中,假设我的变量名称为 vbird ,且内容为 /home/vbird/testing/testing.x.sh。
1. 完整呈现 vbird 这个变量的内容; [root@linux ~]# vbird="/home/vbird/testing/testing.x.sh" [root@linux ~]# echo ${vbird} /home/vbird/testing/testing.x.sh 2. 在 vbird 变量中,从最前面开始比对,若开头为 / ,则删除两个 / 之间的所有数据,亦即 /*/ [root@linux ~]# echo ${vbird##/*/} testing.x.sh <==删除了 /home/vbird/testing/ [root@linux ~]# echo ${vbird#/*/} vbird/testing/testing.x.sh <==仅删除 /home/ 而已 # 这两个小例子有趣了~变量名称后面如果接了两个 ## ,表示在 ## # 后面的字符串取『最长的』那一段;如果仅有一个 # ,表示取『最小的那一段』喔! 3. 承上题,如果是从后面开始,删除 /* 呢? [root@linux ~]# echo ${vbird%%/*/} /home/vbird/testing/testing.x.sh <==都没被删除 [root@linux ~]# echo ${vbird%%/*} <==被删除光了! [root@linux ~]# echo ${vbird%/*} /home/vbird/testing <==只删除 /testing.x.sh 部分 # 这个例子当中需要特别注意,那个 % 比对的是『最后面那个字符』的意思, # 所以啰,第一个方式当然不对~因为 vbird 这个变量的内容最后面是 h 而不是 / 啊! # 至于 %%/* 则是删除『最长的那个 /* 』,当然就是全部喔!而 %/* 则是最短的那个! 4. 将 vbird 变量中的 testing 取代为 TEST [root@linux ~]# echo ${vbird/testing/TEST} /home/vbird/TEST/testing.x.sh [root@linux ~]# echo ${vbird//testing/TEST} /home/vbird/TEST/TEST.x.sh # 如果变量后面接的是 / 时,那么表示后面是进行『取代』的工作~而且仅取代『第一个』 # 但如果是 // ,则表示全部的字符串都取代啊!这里您稍微留意一下就好了~反正就是变量后面可以接 #, ##, %, %%, /, // , 而他们存在的意义并不相同的啦~
变量设置方式 | str 没有设置 | str 为空字符串 | str 已设置非为空字符串 |
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} | str=expr var=expr |
str 不变 var= | str 不变 var=$str |
var=${str:=expr} | str=expr var=expr |
str=expr var=expr | str 不变 var=$str |
var=${str?expr} | expr 输出至 stderr | var= | var=str |
var=${str:?expr} | expr 输出至 stderr | expr 输出至 stderr | var=str |
范例一:若 str 这个变量内容存在,则 var 设置为 str ,否则 var 设置为 "newvar" [root@linux ~]# unset str; var=${str-newvar} [root@linux ~]# echo var="$var", str="$str" var=newvar, str= <==因为 str 不存在,所以 var 为 newvar [root@linux ~]# str="oldvar"; var=${str-newvar} [root@linux ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容 范例二:若 str 不存在,则 var 与 str 均设置为 newvar,否则 var 与 str 相同 [root@linux ~]# unset str; var=${str=newvar} [root@linux ~]# echo var="$var", str="$str" var=newvar, str=newvar <==因为 str 不存在,所以 var/str 均为 newvar [root@linux ~]# str="oldvar"; var=${str=newvar} [root@linux ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容 范例三:若 str 这个变量存在,则 var 等于 str ,否则输出 "novar" [root@linux ~]# unset str; var=${str?novar} -bash: str: novar <==因为 str 不存在,所以输出错误消息 [root@linux ~]# str="oldvar"; var=${str?novar} [root@linux ~]# echo var="$var", str="$str" var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容 # 上面这三个案例都没有提到当 str 有设置,且为空字符串的情况喔! # 您可以自行测试一下哩!
[root@linux ~]# alias lm='ls -l | more'
嘿嘿!我立刻多出了一个可以运行的指令喔!这个指令名称为 lm ,且其实他是运行
ls -al | more 啊!真是方便。不过,
要注意的是:『alias 的定义规则与变量定义规则几乎相同』,
所以你只要在 alias 后面加上你的 {『别名』='指令 参数' },
以后你只要输入 lm 就相当于输入了 ls -al|more 这一串指令!很方便吧!
[root@linux ~]# alias rm='rm -i'
嘿嘿!那么以后使用 rm 的时候,就不用太担心会有错误删除的情况了!这也是命令别名的优点啰!
那么如何知道目前有哪些的命令别名呢?就使用 alias 呀!
[root@linux ~]# alias
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias lm='ls -al | more'
alias ls='ls --color=tty'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
由上面的数据当中,您也会发现一件事情啊,我们在 vi 文书编辑器 里面提到
vi 与 vim 是不太一样的, vi 是比较老,而 vim 可以用来取代 vi 喔。我们的 FC4 明明就同时有 vi/vim ,
为何我运行 vi 会是进入 vim 呢?呵呵!那就是因为上面的表格当中的『 alias vi='vim' 』这个设置啦!
至于如果要取消命令别名的话,那么就使用 unalias 吧!例如要将刚刚的 lm 命令别名拿掉,就使用:
[root@linux ~]# unalias lm
那么命令别名与变量有什么不同呢?基本上,他们的意义就不太一样了! alias
这种命令别名,你可以将他想成是创建一个新的指令名称,
至于变量则仅是将一个数值或者字符串存在某个代表意义当中!举个例子好了,我们知道以前的
DOS 年代,列出目录与文件就是 dir ,而清除屏幕就是 cls ,那么如果我想要在
linux 里面也使用相同的指令呢?那就以 alias 来进行指令的别名设置:
[root@linux ~]# history [n] [root@linux ~]# history [-c] [root@linux ~]# history [-raw] histfiles 参数: n :数字,意思是『要列出最近的 n 笔命令行表』的意思! -c :将目前的 shell 中的所有 history 内容全部消除 -a :将目前添加的 history 指令添加入 histfiles 中,若没有加 histfiles , 则缺省写入 ~/.bash_history -r :将 histfiles 的内容读到目前这个 shell 的 history 记忆中; -w :将目前的 history 记忆内容写入 histfiles 中! 范例: 范例一:列出目前内存内的所有 history 记忆 [root@linux ~]# history # 前面省略 1017 man bash 1018 ll 1019 history 1020 history # 列出的信息当中,共分两栏,第一栏为该指令在这个 shell 当中的代码, # 另一个则是指令本身的内容喔!至于会秀出几笔指令记录,则与 HISTSIZE 有关! 范例二:列出目前最近的 3 笔数据 [root@linux ~]# history 3 1019 history 1020 history 1021 history 3 范例三:立刻将目前的数据写入 histfile 当中 [root@linux ~]# history -w # 在缺省的情况下,会将历史纪录写入 ~/.bash_history 当中! [root@linux ~]# echo $HISTSIZE 1000在正常的情况下,当我们以 bash 登录 Linux 主机之后,系统会主动的由家目录的 ~/.bash_history 读取以前曾经下过的指令,那么 ~/.bash_history 会记录几笔数据呢?这就与你 bash 的 HISTSIZE 这个变量设置值有关了!在缺省的 FC4 底下,是会记录 1000 笔数据的! 那么假设我这次登录主机后,共下达过 100 次指令,『等我注销时, 系统就会将 101~1100 这总共 1000 笔历史命令更新到 ~/.bash_history 当中。』 也就是说,历史命令在我注销时,会将最近的 HISTSIZE 笔记录到我的纪录档当中啦! 当然,也可以用 history -w 强制立刻写入的!那为何用『更新』两个字呢? 因为 ~/.bash_history 记录的笔数永远都是 HISTSIZE 那么多,旧的消息会被主动的拿掉! 仅保留最新的!
[root@linux ~]# !number [root@linux ~]# !command [root@linux ~]# !! 参数: number :运行第几笔指令的意思; command :由最近的指令向前搜索『指令串开头为 command』的那个指令,并运行; !! :就是运行上一个指令(相当于按↑按键后,按 Enter) 范例: [root@linux ~]# history 66 man rm 67 alias 68 man history 69 history [root@linux ~]# !66 <==运行第 66 笔指令 [root@linux ~]# !! <==运行上一个指令,本例中亦即 !66 [root@linux ~]# !al <==运行最近以 al 为开头的指令(上头列出的第 67 个)经过上面的介绍,瞭乎?历史命令用法可多了!如果我想要运行上一个指令, 除了使用上下键之外,我可以直接以『 !! 』 来下达上个指令的内容,此外, 我也可以直接选择下达第 n 个指令,『 !n 』来运行,也可以使用指令标头,例如 『 !vi 』来运行最近指令开头是 vi 的指令列!相当的方便而好用!基本上 history 的用途很大的!但是需要小心安全的问题!尤其是 root 的历史纪录文件,这是 Cracker 的最爱!因为不小心的 root 会将很多的重要数据在运行的过程中会被纪录在 ~/.bash_history 当中,如果这个文件被解析的话,后果不堪呐!无论如何,使用 history 配合『 ! 』曾经使用过的指令下达是很有效率的一个指令方法!
[root@linux ~]# /bin/more .bashrc
我在的目录为 /home/test !这是绝对路径写法! 而如果你还记得我们在
Linux 文件与目录管理 那一篇文章中提到的观念的话,那么应该记得使用
ls -al 时会出现两个一定存在的目录,分别是『.』与『..』,分别代表是『这个路径』,与『上一层路径』!
[root@linux ~]# ls -al
drwxrwxr-x 2 root root 4096 Aug 15 11:05 .
drwxrwxr-x 2 root root 4096 Aug 14 23:26 ..
所以说,要运行上一层目录中的命令,可以下达『../command 』那个 command
指的是存在的可运行档!那么我因为在 /home/test 里面,距离 /bin 有两层上层目录,所以我要使用
/bin/more 这个运行档,并且使用相对路径的方法,就必须使用:
[root@linux ~]# ../../bin/more .bashrc
这种相对路径的方法相当广泛的被运用于 script 当中,这是因为如前面提到的,
每个人的安装缺省的目录都不相同,则使用相对路径的话,
很容易就可以找到套件之间相依软件或者是设置文件的相关性!
例题:关于路径搜索的问题!为何不运行目前所在目录下的文件? 答:
那么为何不要设置这个路径呢?这是因为『 安全』的考量。由于系统缺省是允许任何人在 /tmp 底下写入任何文件的,那么万一有居心不良的用户或者是 Cracker 入侵你的电脑,并在你的 /tmp 里头埋了一个小木马,并取名为 ls ,好了,改天你以 root 身份登录后,到 /tmp 底下,并运行 ls ,你看会有什么结果?!这个 /tmp/ls 由其他身份的人来运行或许没有问题,但是由 root 来运行却可能会导致 Cracker 所乐意见到的结果!那晓得为何了吧?! 当然啰!您还是可以选择在 ~/.bashrc 当中设置你的 . 在你的 PATH 当中,不过并不这么建议就是了! |
[root@linux ~]# ./squid
请特别留意这方面的问题!『新手特别容易犯这个错误呢!』
[root@linux ~]# cat /etc/issue
Fedora Core release 4 (Stentz)
Kernel \r on an \m
在 FC4 里面缺省有三行,这个在我们本机登录时就会显示在 title 的地方呢~
咦!那么那个 \r 及 \m 是啥?您可以使用 man issue 配合 man mingetty 就能够知道:issue 内的各代码意义 |
\d 本地端时间的日期; \l 显示第几个终端机接口; \m 显示硬件的等级 (i386/i486/i586/i686...); \n 显示主机的网络名称; \o 显示 domain name; \r 操作系统的版本 (相当于 uname -r) \t 显示本地端时间的时间; \s 操作系统的名称; \v 操作系统的版本。 |
[root@linux ~]# vi /etc/motd Hello everyone, Our server will be maintained at 2005/10/10 0:00 ~ 24:00. Please don't login at that time. ^_^那么当你的用户登录主机后,就会显示这样的消息出来:
Last login: Mon Aug 15 10:17:10 2005 from 127.0.0.1 Hello everyone, Our server will be maintained at 2005/10/10 0:00 ~ 24:00. Please don't login at that time. ^_^是否很方便啊!? ^_^
[root@linux ~]# cat /etc/sysconfig/i18n
LANG="zh_TW.UTF-8"
SYSFONT="latarcyrheb-sun16"
SUPPORTED="zh_TW.UTF-8:zh_TW:zh:en_US.UTF-8"
我缺省使用 zh_TW.UTF-8 来作为我的整体语系,当然,我可以在这里修改 LANG 以及其他相关的语系变量,
例如 LC_CTYPE 或者是 LC_TIME 等等的。不过,一般来说,用户自己个人的设置不建议在这里做更动啦!
他们可以自行设置他们自己的设置档啊!
[root@linux ~]# vi ~/.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific aliases and functions
PATH="/bin:/sbin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
PATH="$PATH":/usr/X11R6/bin:/home/dmtsai/bin
LANG=zh_TW.big5
LC_TIME=C
export PATH LC_TIME LANG
umask 022
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias ll='ls -l'
alias lm='ls -al|more'
alias h='history'
仔细看到上头这个文件,会不会觉得奇怪啊!为什么会有第五行的『 . /etc/bashrc 』呢?
那个小数点 (.) 代表什么意思啊??其实 if [ ... ]; then .... fi 是 shell script 当中的程序写法,
这个我们会在下一章当中介绍。不过,那个 . 则需要好好的谈一谈喔!一般来说,如果修改完了设置档,
通常就是 logout 后再重新 login 到 bash 内,就能够将环境设置档重读了!不过,
我们可以使用底下的方式来让该设置档立即生效:[root@linux ~]# source file 范例: [root@linux ~]# source ~/.bashrc [root@linux ~]# . ~/.bashrc利用 source 或小数点 (.) 都可以将设置档的内容读进来目前的 shell 环境中! 举例来说,我修改了 ~/.bashrc ,那么不需要注销,立即以 source ~/.bashrc 就可以将刚刚最新设置的内容读进来目前的环境中!很不错吧!此外,什么时候会使用到不同的设置档呢? 最常发生在一个人的工作环境分为多重的时候了!举个例子来说,在我的大型主机中, 我常常需要负责两到三个不同的案子,每个案子所需要处理的环境变量订定并不相同, 那么我就将这两三个案子分别编写属于该案子的环境变量设置文件,当我需要该环境时,就直接『 source 变量档 』,如此一来,环境变量的设置就变的更简便而灵活了!
[root@linux ~]# stty [-a] 参数: -a :将目前所有的 stty 参数表出来; 范例: 范例一:列出所有的按键与按键内容 [root@linux ~]# stty -a speed 38400 baud; rows 40; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol =我们可以利用 stty -a 来列出目前环境中所有的按键列表,在上头的列表当中,需要注意的是特殊字体那几个, 此外,如果出现 ^ 表示 [Ctrl] 那个按键的意思。举例来说, intr = ^C 表示利用 [ctrl] + c 来达成的。 几个重要的代表意义是:; eol2 = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
[root@linux ~]# stty erase ^h
那么从此之后,你的删除字符就得要使用 [ctrl]+h 啰,按下 [backspace] 则会出现 ^? 字样呢!
如果想要回复利用 [backspace] ,就下达 stty erase ^? 即可啊!
至于更多的 stty 说明,记得参考一下 man stty 的内容喔![root@linux ~]# set [-uvCHhmBx] 参数: -u :缺省不激活。若激活后,当使用未设置变量时,会显示错误消息; -v :缺省不激活。若激活后,在消息被输出前,会先显示消息的原始内容; -x :缺省不激活。若激活后,在指令被运行前,会显示指令内容(前面有 ++ 符号) -h :缺省激活。与历史命令有关(下节介绍); -H :缺省激活。与历史命令有关(下节介绍); -m :缺省激活。与工作管理有关(未来介绍); -B :缺省激活。与刮号 [] 的作用有关; -C :缺省不激活。若使用 > 等,则若文件存在时,该文件不会被覆盖。 范例: 范例一:显示目前所有的 set 设置值 [root@linux ~]# echo $- himBH # 那个 $- 变量内容就是 set 的所有设置啦! bash 缺省是 himBH 喔! 范例二:设置 "若使用未定义变量时,则显示错误消息" [root@linux ~]# set -u [root@linux ~]# echo $vbirding -bash: vbirding: unbound variable # 缺省情况下,未设置/未声明 的变量都会是『空的』,不过,若设置 -u 参数, # 那么当使用未设置的变量时,就会有问题啦!很多的 shell 都缺省激活 -u 参数。 # 若要取消这个参数,输入 set +u 即可! 范例三:运行前,显示该指令内容。 [root@linux ~]# set -x [root@linux ~]# echo $HOME + echo /root /root ++ echo -ne '\033]0;root@linux:~\007' # 看见否?要输出的指令都会先被打印到屏幕上喔!前面会多出 + 的符号!另外,其实我们还有其他的按键设置功能呢!就是在 /etc/inputrc 这个文件里面设置。
[root@linux ~]# cat /etc/inputrc # do not bell on tab-completion #set bell-style none set meta-flag on set input-meta on set convert-meta off set output-meta on .....以下省略.....还有例如 /etc/DIR_COLORS* 与 /etc/termcap 等,也都是与终端机有关的环境设置文件呢! 不过,事实上,鸟哥并不建议您修改 tty 的环境呢,这是因为 bash 的环境已经设置的很亲和了, 我们不需要额外的设置或者修改,否则反而会产生一些困扰。不过,写在这里的数据, 只是希望大家能够清楚的知道我们的终端机是如何进行设置的喔! ^_^
符号 | 内容 |
* | 通配符,代表 0 个或多个字符(或数字) |
? | 通配符,代表『一定有』一个字母 |
# | 注解,这个最常被使用在 script 当中,视为说明! |
\ | 跳脱符号,将『特殊字符或通配符』还原成一般字符 |
| | 分隔两个管线命令的界定; |
; | 连续性命令的界定(注意!与管线命令并不相同) |
~ | 用户的家目录 |
$ | 亦即是变量之前需要加的变量取代值 |
& | 将指令变成背景下工作 |
! | 逻辑运算意义上的『非』 not 的意思! |
/ | 路径分隔的符号 |
>, >> | 输出导向,分别是『取代』与『累加』 |
' | 单引号,不具有变量置换的功能 |
" | 具有变量置换的功能! |
` ` | 两个『 ` 』中间为可以先运行的指令! |
( ) | 在中间为子 shell 的起始与结束 |
[ ] | 在中间为字符的组合 |
{ } | 在中间为命令区块的组合! |
组合按键 | 运行结果 |
Ctrl + C | 终止目前的命令 |
Ctrl + D | 输入结束(EOF),例如邮件结束的时候; |
Ctrl + M | 就是 Enter 啦! |
Ctrl + S | 暂停屏幕的输出 |
Ctrl + Q | 恢复屏幕的输出 |
Ctrl + U | 在提示字符下,将整列命令删除 |
Ctrl + Z | 『暂停』目前的命令 |
[root@linux ~]# ls test* <==那个 * 代表后面不论接几个字符都予以接受 [root@linux ~]# ls test? <==那个 ? 代表后面『一定』要接『一个』字符 [root@linux ~]# ls test??? <==那个 ??? 代表『一定要接三个』字符! [root@linux ~]# cp test[1-5] /tmp # 将 test1, test2, test3, test4, test5 若存在的话,就拷贝到 /tmp [root@linux ~]# cp test[!1-5] /tmp # 只要不是 test1, test2, test3, test4, test5 之外的其他 test? , # 若存在的话,就拷贝到 /tmp [root@linux ~]# cd /lib/modules/`uname -r`/kernel/drivers # 被 ` ` 括起来的内容『会先运行』上面几个例子相当的有趣!尤其是最后面两个!需要注意的是, [1-5] 里面『代表只有一个字符』但是范围可以由 1-5 ,这样来说的话,那么我们如果允许『只要文件名里面含有至少一个大写字符』时,就可以将文件 copy 出来的话,可以这样做:
[root@linux ~]# ls -l / > ~/rootfile # 本来 ls -l / 会将根目录的数据列出到屏幕上; # 现在我使用了 > ~/rootfile 后,则本来应该在屏幕上出现的数据 # 就会被『重新导向』到 ~/rootfile 文件内了!就可以将该数据保存!此时,原本应该在屏幕上面出现的数据通通不见去~因为那些数据都被写入到 ~/rootfile 去了! 当然,那个文件的文件名随便你取啦~如果你下达:『 cat ~/rootfile 』就可以看到原本应该在屏幕上面的数据啰。 那么如果我再次下达:『 ls -l /home > ~/rootfile 』后,那么那个 ~/rootfile 文件的内容变成什么? 呵呵!变成『仅有 ls -l /home 的数据』而已!咦!原本的 ls -l / 数据就不见了吗?是的! 因为该文件的创建方式是:
command | > 1> 2> 2>> < | 设备或文件 |
范例一:将目前目录下的文件信息全部保存到 list.txt 文件中 [root@linux ~]# ls -al > list.txt 范例二:将根目录下的数据也保存到 list.txt 文件中 [root@linux ~]# ls -al / >> list.txt好了,对于『 > , >> 』这两个东西有一定的概念之后,我们来深入的谈一谈『数据流重导向』的观念吧! 如前所述,基本上, Linux 运行的结果中,可以约略的分成『正确输出』与『错误输出』两种数据。 例如,当你以一般身份运行 find 这个指令时,例如运行『 find / -name testing 』时,由于你是一般身份,又有些文件夹是不允许一般身份者进入的, 所以啰,当你使用 find 时,就会有错误消息发生了!但同时如果有 testing 这个文件在你可以进入的文件夹当中,那么屏幕也会输出到给你看!因此, 就具有正确的与错误的输出两种啰!(分别称为 Stdout 与 Stderror)例如下面为运行结果: 里面的『 find: /home/root: Permission denied 』就告诉你该文件夹你没有权限进入, 这就是错误的输出了,那么『 /home/dmtsai/tseting 』就是正确的输出了!
[dmtsai@linux ~]$ find /home -name testing find: /home/test1: Permission denied <== Starndard error find: /home/root: Permission denied <== Starndard error find: /home/masda: Permission denied <== Starndard error /home/dmtsai/testing <== Starndard output好了,那么假如我们想要将数据输出到 list 这个文件中呢?运行『 find / -name testing > list 』 会有什么结果?呵呵,你会发现 list 里面存了刚刚那个『正确』的输出数据, 至于屏幕上还是会有错误的消息出现呢!伤脑筋!如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?! 呵呵!其实在数据的重导向方面,正确的写法应该是『 1> 』与『 2> 』才对!但是如果只有 > 则缺省是以 1> 来进行数据的!那个 1> 是输出正确数据, 2> 则是错误数据输出项目。也就是说:
[dmtsai@linux ~]$ find /home -name testing > list_right 2> list_error
这样一来,刚刚运行的结果中,有 Permission 的那几行错误信息都会跑到 list_error
这个文件中,至于正确的输出数据则会存到 list_right 这个文件中啰!这样可以了解了吗?
如果有点混乱的话,去休息一下再来看看吧!!
[dmtsai@linux ~]$ find /home -name testing > list_right 2> /dev/null
很神奇呦! error message 就会『不见了!』呵呵!真高兴!另外,
如果我要将数据都写到同一个文件中呢?这个时候写法需要用到特殊写法,请注意底下的写法呦![dmtsai@linux ~]$ find /home -name testing > list 2> list <==错误写法 [dmtsai@linux ~]$ find /home -name testing > list 2>&1 <==正确写法请特别留意这一点呢!同时写入同一个文件需要使用 2>&1 才对呦!
[root@linux ~]# cat > catfile testing cat file test <==这里按下 [ctrl]+d 结束输入来离开!此时就会有 catfile 这个文件产生,而且该文件的内容就是刚刚输入的内容喔。 那么,我是否可以使用其他文件来取代键盘输入呢?可以啊!这样做!
[root@linux ~]# cat > catfile < somefile
我可以先编辑 somefile ,然后再以上述的指令来将数据输出到 catfile 去呢!这样可以理解了吗?
能够理解 < 之后,再来则是怪可怕一把的 << 这个连续两个小于的符号了~
他代表的是『结束的输入字符』的意思!举例来讲:『我要用 cat 直接将输入的消息输出到 catfile 中,
且当输入 eof 时,该次输入就结束』,那我可以这样做:[root@linux ~]# cat > catfile <<eof > This is a test testing > OK now stop > eof <==输入这个玩意儿,嘿!立刻就结束了!看到了吗?利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束哩!这对程序写作很有帮助喔!好了,那么为何要使用命令输出重导向呢? 这个问题一定会困扰你一下下的,如果你从来都没有写过 script 的话!好了,我们来说一说吧!
[root@linux ~]# sync; sync; shutdown -h now
在指令与指令中间利用分号 (;) 来隔开,这样一来,分号前的指令运行完后,
就会立刻接着运行后面的指令了。这真是方便啊~再来,换个角度来想,
万一我想要在某个目录底下创建一个文件,也就是说,如果该目录存在的话,
那我才创建这个文件,如果不存在,那就算了~目录是否存在可以使用一些 bash 提供的判断式功能,
但这里假设我不晓得那个指令,但我知道我可以使用 ls 来判断是否有该目录的存在,
也就是说,我可以利用 ls directoryname 判断是否存在,然后以 touch 创建一个文件,
这两个指令有相关性,那该如何写呢?呵呵!可以利用 && 来作喔!
[root@linux ~]# ls /tmp && touch /tmp/testingagin
是否记得我们在变量的章节里面谈过这个奇怪的变量『 $? 』呢?
如果指令运行结果没有错误消息,那就会回传 $?=0 ,如果有错误,
那回传值就不会是 0 啊!经由这样的判断,我们也可以利用 && 来决定,
当前面的指令运行结果为正确 (例如:仅有 standard output 时),就可以接着运行后续的指令,
否则就予以略过!因此,当 ls /tmp 没有问题,那么就会接着运行 touch /tmp/testingagin 了!
万一是这样:
[root@linux ~]# ls /vbird && touch /vbird/test
因为我的系统里面根本就不可能存在 /vbird 这个目录呢!所以,运行 ls /vbird 就会回传错误,
那么后续的 touch /vbird/test 自然就不会动作啰!了解吗?
[root@linux ~]# ls /tmp/vbirding || touch /tmp/vbirding
那个 || 刚好完全跟 && 相反,当前一个指令有错误时,在 || 后面的指令才会被运行!
(要注意,那个 | 是两个 | ,而 | 按键则是反斜线 \ 同一个按键,
因此,按下 [Shift] 加上 [\] 就会出现那个 | 啰!)
因此,简单的来说,当 ls /tmp/vbirding 发生错误时,才会使用 touch /tmp/vbirding 去创建这个文件的意思。
是否很有趣啊?这个 || 及 && 对于系统管理员在管理某些文件权限、存在等问题时,
可是很有用的东西喔!好了,现在我们来玩比较难一点的,看看底下的例题:
例题:以 ls 测试 /tmp/vbirding 是否存在,若存在则显示 "exist" ,若不存在,则显示 "not exist"! 答:
ls /tmp/vbirding && echo "exist" || echo "not exist" 意思是说,当 ls /tmp/vbirding 运行后,若正确,就运行 echo "exist" ,若有问题,就运行 echo "not exist" ! 那如果我写成: ls /tmp/vbirding || echo "not exist" && echo "exist" 对不对啊?这其实是有问题的,为什么呢?因为指令是一个一个往下运行,因此,在上面的例子当中,如果 /tmp/vbirding 不存在时,他会: 所以啊,嘿嘿!第二个例子里面竟然会同时出现 not exist 与 exist 呢!真神奇~ |
[root@linux ~]# ls -al /etc | less
嘿嘿!如此一来,使用 ls 指令输出后的内容,就能够被 less 读取,
并且利用 less 的功能,我们就能够前后翻动相关的信息了!很方便是吧?呵呵!
我们就来了解一下这个管线命令『 | 』的用途吧![root@linux ~]# cut -d'分隔字符' -f fields [root@linux ~]# cut -c 字符区间 参数: -d :后面接分隔字符。与 -f 一起使用; -f :依据 -d 的分隔字符将一段消息分割成为数段,用 -f 取出第几段的意思; -c :以字符 (characters) 的单位取出固定字符区间; 范例: 范例一:将 PATH 变量取出,我要找出第五个路径。 [root@linux ~]# echo $PATH /bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games: [root@linux ~]# echo $PATH | cut -d ':' -f 5 # 嘿嘿!如此一来,就会出现 /usr/local/bin 这个目录名称! # 因为我们是以 : 作为分隔符号,第五个就是 /usr/local/bin 啊! # 那么如果想要列出第 3 与第 5 呢?,就是这样: [root@linux ~]# echo $PATH | cut -d ':' -f 3,5 范例二:将 export 输出的消息,取得第 12 字符以后的所有字符串 [root@linux ~]# export declare -x HISTSIZE="1000" declare -x INPUTRC="/etc/inputrc" declare -x KDEDIR="/usr" declare -x LANG="zh_TW.big5" ......其他省略...... [root@linux ~]# export | cut -c 12- HISTSIZE="1000" INPUTRC="/etc/inputrc" KDEDIR="/usr" LANG="zh_TW.big5" ......其他省略...... # 知道怎么回事了吧?用 -c 可以处理比较具有格式的输出数据! # 我们还可以指定某个范围的值,例如第 12-20 的字符,就是 cut -c 12-20 等等! 范例三:用 last 将这个月登录者的信息中,仅留下用户大名 [root@linux ~]# last vbird tty1 192.168.1.28 Mon Aug 15 11:55 - 17:48 (05:53) vbird tty1 192.168.1.28 Mon Aug 15 10:17 - 11:54 (01:37) [root@linux ~]# last | cut -d ' ' -f 1 # 用 last 可以取得最近一个月登录主机的用户信息, # 而我们可以利用空白字符的间隔,取出第一个信息,就是用户帐号啰! # 但是因为 vbird tty1 之间空格有好几个,并非仅有一个,所以,如果要找出 # tty1 其实不能以 cut -d ' ' -f 1,2 喔!输出的结果会不是我们想要的。这个 cut 实在很好用!不过,说真的,除非你常常在分析 log 文件,否则使用到 cut 的机会并不多!好了! cut 主要的用途在于将『同一行里面的数据进行分解!』, 最常使用在分析一些数据或文本数据的时候!这是因为有时候我们会以某些字符当作分割的参数, 然后来将数据加以切割,以取得我们所需要的数据。我也很常使用这个功能呢!尤其是在分析 log 文件的时候!不过, cut 在处理多空格相连的数据时,可能会比较吃力一点~
[root@linux ~]# grep [-acinv] '搜索字符串' filename 参数: -a :将 binary 文件以 text 文件的方式搜索数据 -c :计算找到 '搜索字符串' 的次数 -i :忽略大小写的不同,所以大小写视为相同 -n :顺便输出行号 -v :反向选择,亦即显示出没有 '搜索字符串' 内容的那一行! 范例: 范例一:将 last 当中,有出现 root 的那一行就取出来; [root@linux ~]# last | grep 'root' 范例二:与范例一相反,只要没有 root 的就取出! [root@linux ~]# last | grep -v 'root' 范例三:在 last 的输出消息中,只要有 root 就取出,并且仅取第一栏 [root@linux ~]# last | grep 'root' |cut -d ' ' -f1 # 在取出 root 之后,利用上个指令 cut 的处理,就能够仅取得第一栏啰!grep 是个很棒的指令喔!他支持的语法实在是太多了~用在正规表示法里头, 能够处理的数据实在是多的很~不过,我们这里先不谈正规表示法~下一章再来说明~ 您先了解一下, grep 可以解析一行文本,取得关键字,若该行有存在关键字, 就会整行列出来!
[root@linux ~]# sort [-fbMnrtuk] [file or stdin] 参数: -f :忽略大小写的差异,例如 A 与 a 视为编码相同; -b :忽略最前面的空白字符部分; -M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法; -n :使用『纯数字』进行排序(缺省是以文本型态来排序的); -r :反向排序; -u :就是 uniq ,相同的数据中,仅出现一行代表; -t :分隔符号,缺省是 tab 键; -k :以那个区间 (field) 来进行排序的意思, 范例: 范例一:个人帐号都记录在 /etc/passwd 下,请将帐号进行排序。 [root@linux ~]# cat /etc/passwd | sort adm:x:3:4:adm:/var/adm:/sbin/nologin apache:x:48:48:Apache:/var/www:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # 我省略很多的输出~由上面的数据看起来, sort 是缺省『以第一个』数据来排序, # 而且缺省是以『文本』型态来排序的喔!所以由 a 开始排到最后啰! 范例二:/etc/passwd 内容是以 : 来分隔的,我想以第三栏来排序,该如何? [root@linux ~]# cat /etc/passwd | sort -t ':' -k 3 root:x:0:0:root:/root:/bin/bash iiimd:x:100:101:IIIMF server:/usr/lib/iiim:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin # 看到特殊字体的输出部分了吧?怎么会这样排列啊?呵呵!没错啦~ # 如果是以文本型态来排序的话,原本就会是这样,想要使用数字排序: # cat /etc/passwd | sort -t ':' -k 3 -n # 这样才行啊!用那个 -n 来告知 sort 以数字来排序啊! 范例三:利用 last ,将输出的数据仅取帐号,并加以排序 [root@linux ~]# last | cut -d ' ' -f1 | sortsort 同样是很常用的指令呢!因为我们常常需要比较一些信息啦! 举个上面的第二个例子来说好了!今天假设你有很多的帐号,而且你想要知道最大的用户 ID 目前到哪一号了!呵呵!使用 sort 一下子就可以知道答案咯!当然其使用还不止此啦! 有空的话不妨玩一玩!
[root@linux ~]# uniq [-ic] 参数: -i :忽略大小写字符的不同; -c :进行计数 范例: 范例一:使用 last 将帐号列出,仅取出帐号栏,进行排序后仅取出一位; [root@linux ~]# last | cut -d ' ' -f1 | sort | uniq 范例二:承上题,如果我还想要知道每个人的登录总次数呢? [root@linux ~]# last | cut -d ' ' -f1 | sort | uniq -c这个指令用来将『重复的行删除掉只显示一个』,举个例子来说, 你要知道这个月份登录你主机的用户有谁,而不在乎他的登录次数,那么就使用上面的范例, (1)先将所有的数据列出;(2)再将人名独立出来;(3)经过排序;(4)只显示一个! 由于这个指令是在将重复的东西减少,所以当然需要『配合排序过的文件』来处理啰!
[root@linux ~]# wc [-lwm] 参数: -l :仅列出行; -w :仅列出多少字(英文单字); -m :多少字符; 范例: 范例一:那个 /etc/man.config 里面到底有多少相关字、行、字符数? [root@linux ~]# cat /etc/man.config | wc 138 709 4506 # 输出的三个数字中,分别代表: 『行、字数、字符数』 范例二:我知道使用 last 可以输出登录者,但是 last 最后两行并非帐号内容, 那么请问,我该如何以一行指令串取得这个月份登录系统的总人次? [root@linux ~]# last | grep [a-zA-Z] | grep -v 'wtmp' | wc -l # 由于 last 会输出空白行与 wtmp 字样在最底下两行,因此,我利用 # grep 取出非空白行,以及去除 wtmp 那一行,在计算行数,就能够了解啰!wc 也可以当作指令?呵呵!这可不是上洗手间的 WC 呢! 这是相当有用的计算文件内容的一个工具组喔!举个例子来说, 当你要知道目前你的帐号文件中有多少个帐号时,就使用这个方法:『 cat /etc/passwd | wc -l 』啦!因为 /etc/passwd 里头一行代表一个用户呀! 所以知道行数就晓得有多少的帐号在里头了!而如果要计算一个文件里头有多少个字符时,呵呵!就使用 wc -c 这个参数吧!
[root@linux ~]# tee [-a] file 参数: -a :以累加 (append) 的方式,将数据加入 file 当中! 范例: [root@linux ~]# last | tee last.list | cut -d " " -f1 # 这个范例可以让我们将 last 的输出存一份到 last.list 文件中; [root@linux ~]# ls -l /home | tee ~/homefile | more # 这个范例则是将 ls 的数据存一份到 ~/homefile ,同时屏幕也有输出消息! [root@linux ~]# ls -l / | tee -a ~/homefile | more # 要注意: tee 后接的文件会被覆盖,所以,我们要加上 -a # 这个参数才能将消息累加。有没有发现在命令重导向的时候,如果我们要将数据送出到文件的时候, 屏幕上就不会出现任何的数据!那么如果我们需要将数据同时显示在屏幕上跟文件中呢?呵呵!这个时候就需要 tee 这个指令啰!使用 last 可以查看到这个月份的登录数据,而使用了 tee 之后,会将数据同时传给下一个命令去运行,也会将数据写入 last.list 这个文件中!也是个好帮手!
[root@linux ~]# tr [-ds] SET1 ... 参数: -d :删除消息当中的 SET1 这个字符串; -s :取代掉重复的字符! 范例: 范例一:将 last 输出的消息中,所有的小写变成大写字符: [root@linux ~]# last | tr '[a-z]' '[A-Z]' 范例二:将 /etc/passwd 输出的消息中,将冒号 (:) 删除 [root@linux ~]# cat /etc/passwd | tr -d ':' 范例三:将 DOS 文件的断行字符 ^M 符号删除: [root@linux ~]# cat /home/test/dostxt | tr -d '\r' > dostxt-noM # 那个 \r 指的是 DOS 的断行字符,关于更多的字符,请参考 man tr其实这个指令也可以写在『正规表示法』里头!因为他也是由正规表示法的方式来取代数据的! 以上面的例子来说,使用 [] 可以设置一串字呢! 也常常用来取代文件中的怪异符号! 例如上面第三个例子当中,可以去除 DOS 文件留下来的 ^M 这个断行的符号!这东西相当的有用!相信处理 Linux & Windows 系统中的人们最麻烦的一件事就是这个事情啦!亦即是 DOS 底下会自动的在每行行尾加入 ^M 这个断行符号!这个时候我们可以使用这个 tr 来将 ^M 去除! ^M 可以使用 \r 来代替之!
[root@linux ~]# col [-x] 参数: -x :将 tab 键转换成对等的空白键 范例: [root@linux ~]# cat -A /etc/man.config <==此时会看到很多 ^I 的符号,那就是 tab [root@linux ~]# cat /etc/man.config | col -x | cat -A | more # 嘿嘿!如此一来, [tab] 按键会被取代成为空白键,输出就美观多了!虽然 col 有他特殊的用途,不过,很多时候,他可以用来简单的处理将 [tab] 按键取代成为空白键! 例如上面的例子当中,如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理,则会将 [tab] 取代成为对等的空白键!
[root@linux ~]# join [-ti12] file1 file2 参数: -t :join 缺省以空白字符分隔数据,并且比对『第一个字段』的数据, 如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个! -i :忽略大小写的差异; -1 :这个是数字的 1 ,代表『第一个文件要用那个字段来分析』的意思; -2 :代表『第二个文件要用那个字段来分析』的意思。 范例: 范例一:用 root 的身份,将 /etc/passwd 与 /etc/shadow 相关数据集成成一栏 [root@linux ~]# join -t ':' /etc/passwd /etc/shadow bin:x:1:1:bin:/bin:/sbin/nologin:*:12959:0:99999:7::: daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:12959:0:99999:7::: adm:x:3:4:adm:/var/adm:/sbin/nologin:*:12959:0:99999:7::: # 因为 /etc/shadow 的权限问题,所以这里必须是 root 才能动作!而 /etc/passwd # 与 /etc/shadow 都是以 : 来分隔字段,所以必须要使用 -t ':' 规范字段分隔字符。 # 且,因为 /etc/shadow 与 /etc/passwd 刚好都是以第一个字段为帐号名称,所以, # 就可以将同一行的数据给他贴在一起了! # 另外,再仔细看一下 /etc/shadow 的内容与 /etc/passwd 的内容,您会发现, # 两者都以帐号为开始,而上面的输出数据中您会发现特殊字体部分,那代表 # 第二个文件的内容。在第二个文件的内容部分,由于帐号(第一个字段)与 # 第一的文件是相同的,所以当然就省略掉,因此就成为上面的输出。 范例二:我们知道 /etc/passwd 第四个字段是 GID ,那个 GID 记录在 /etc/group 当中的第三个字段,请问如何将两个文件集成? [root@linux ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group 0:root:x:0:root:/root:/bin/bash:root:x: 1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:root,bin,daemon 2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:root,bin,daemon 4:adm:x:3:adm:/var/adm:/sbin/nologin:adm:x:root,adm,daemon # 这个例子就更明显了!原本的 /etc/passwd 的第一行内容应该是: # root:x:0:0:root:/root:/bin/bash # 至于 /etc/group 第一行内容应该是: # root:x:0: # 我将第一个文件的第四栏与第二个文件的第三栏取出,放置到输出的最前方, # 然后将剩下的数据给他加在一起!就成了上面的输出啦!这个 join 在处理两个相关的数据文件时,就真的是很有帮助的啦! 例如上面的案例当中,我的 /etc/passwd, /etc/shadow, /etc/group 都是有相关性的, 其中 /etc/passwd, /etc/shadow 以帐号为相关性,至于 /etc/passwd, /etc/group 则以所谓的 GID (帐号的数字定义) 来作为他的相关性。根据这个相关性, 我们可以将有关系的数据放置在一起!这在处理数据可是相当有帮助的! 但是上面的例子有点难,希望您可以静下心好好的看一看原因喔!
[root@linux ~]# paste [-d] file1 file2 参数: -d :后面可以接分隔字符。缺省是以 [tab] 来分隔的! - :如果 file 部分写成 - ,表示来自 standard input 的数据的意思。 范例: 范例一:将 /etc/passwd 与 /etc/shadow 同一行贴在一起 [root@linux ~]# paste /etc/passwd /etc/shadow bin:x:1:1:bin:/bin:/sbin/nologin bin:*:12959:0:99999:7::: daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:12959:0:99999:7::: adm:x:3:4:adm:/var/adm:/sbin/nologin adm:*:12959:0:99999:7::: # 注意喔!同一行中间是以 [tab] 按键隔开的! 范例二:先将 /etc/group 读出(用 cat),然后与范例一粘贴一起!且仅取出前三行 [root@linux ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3 # 这个例子的重点在那个 - 的使用!那玩意儿常常代表 stdin 喔!
[root@linux ~]# expand [-t] file 参数: -t :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空白键取代。 我们也可以自行定义一个 [tab] 按键代表多少个字符呢! 范例: 范例一:将 /etc/man.config 内行首为 MANPATH 的字样就取出;仅取前三行; [root@linux ~]# grep '^MANPATH' /etc/man.config | head -n 3 MANPATH /usr/man MANPATH /usr/share/man MANPATH /usr/local/man # 行首的代表标志为 ^ ,这个我们留待下节介绍!先有概念即可! 范例二:承上,如果我想要将所有的符号都列出来?(用 cat) [root@linux ~]# grep '^MANPATH' /etc/man.config | head -n 3 |cat -A MANPATH^I/usr/man$ MANPATH^I/usr/share/man$ MANPATH^I/usr/local/man$ # 发现差别了吗?没错~ [tab] 按键可以被 cat -A 显示成为 ^I 范例三:承上,我将 [tab] 按键设置成 6 个字符的话? [root@linux ~]# grep '^MANPATH' /etc/man.config | head -n 3 | \ > expand -t 6 - | cat -A MANPATH /usr/man$ MANPATH /usr/share/man$ MANPATH /usr/local/man$ 123456123456123456..... # 仔细看一下上面的数字说明,因为我是以 6 个字符来代表一个 [tab] 的长度,所以, # MAN... 到 /usr 之间会隔 12 (两个 [tab]) 个字符喔!如果 tab 改成 9 的话, # 情况就又不同了!这里也不好理解~您可以多设置几个数字来查阅就晓得!expand 也是挺好玩的~他会自动将 [tab] 转成空白键~所以,以上面的例子来说, 使用 cat -A 就会查不到 ^I 的字符啰~此外,因为 [tab] 最大的功能就是格式排列整齐! 我们转成空白键后,这个空白键也会依据我们自己的定义来增加大小~ 所以,并不是一个 ^I 就会换成 8 个空白喔!这个地方要特别注意的哩! 此外,您也可以参考一下 unexpand 这个将空白转成 [tab] 的指令功能啊! ^_^
[root@linux ~]# split [-bl] file PREFIX 参数: -b :后面可接欲分割成的文件大小,可加单位,例如 b, k, m 等; -l :以行数来进行分割。 范例: 范例一:我的 /etc/termcap 有七百多K,若想要分成 300K 一个文件时? [root@linux ~]# cd /tmp; split -b 300k /etc/termcap termcap [root@linux tmp]# ls -l termcap* -rw-rw-r-- 1 root root 307200 8月 17 00:25 termcapaa -rw-rw-r-- 1 root root 307200 8月 17 00:25 termcapab -rw-rw-r-- 1 root root 184848 8月 17 00:25 termcapac # 那个文件名可以随意取的啦!我们只要写上前导文本,小文件就会以 # xxxaa, xxxab, xxxac 等方式来创建小文件的! 范例二:如何将上面的三个小文件合成一个文件,文件名为 termcapback [root@linux tmp]# cat termcap* >> termcapback # 很简单吧?就用数据流重导向就好啦!简单! 范例三:使用 ls -al / 输出的信息中,每十行记录成一个文件 [root@linux tmp]# ls -al / | split -l 10 - lsroot # 重点在那个 - 啦!一般来说,如果需要 stdout/stdin 时,但偏偏又没有文件, # 有的只是 - 时,那么那个 - 就会被当成 stdin 或 stdout ~在 Windows 的情况下,你要将文件分割需要如何作?!伤脑筋吧!呵呵!在 Linux 底下就简单的多了!你要将文件分割的话,那么就使用 -b size 来将一个分割的文件限制其大小,如果是行数的话,那么就使用 -l line 来分割!好用的很!如此一来,你就可以轻易的将你的文件分割成 floppy 的大小,方便你 copy 啰!
[root@linux ~]# xargs [-0epn] command 参数: -0 :如果输入的 stdin 含有特殊字符,例如 `, \, 空白键等等字符时,这个 -0 参数 可以将他还原成一般字符。这个参数可以用于特殊状态喔! -e :这个是 EOF (end of file) 的意思。后面可以接一个字符串,当 xargs 分析到 这个字符串时,就会停止继续工作! -p :在运行每个指令的 argument 时,都会询问用户的意思; -n :后面接次数,每次 command 指令运行时,要使用几个参数的意思。看范例三。 当 xargs 后面没有接任何的指令时,缺省是以 echo 来进行输出喔! 范例: 范例一:将 /etc/passwd 内的第一栏取出,仅取三行,使用 finger 这个指令将每个 帐号内容秀出来 [root@linux ~]# cut -d':' -f1 < /etc/passwd |head -n 3| xargs finger Login: root Name: root Directory: /root Shell: /bin/bash Never logged in. No mail. No Plan. ......底下省略..... # 由 finger account 可以取得该帐号的相关说明内容,例如上面的输出就是 finger root # 后的结果。在这个例子当中,我们利用 cut 取出帐号名称,用 head 取出三个帐号, # 最后则是由 xargs 将三个帐号的名称变成 finger 后面需要的参数! 范例二:同上,但是每次运行 finger 时,都要询问用户是否动作? [root@linux ~]# cut -d':' -f1 < /etc/passwd |head -n 3| xargs -p finger finger root bin daemon ?...y ......底下省略..... # 呵呵!这个 -p 的参数有趣了吧?!他可以让用户的使用过程中,被询问到每个 # 指令是否运行! 范例三:将所有的 /etc/passwd 内的帐号都以 finger 查阅,但一次仅查阅五个帐号 [root@linux ~]# cut -d':' -f1 < /etc/passwd | xargs -p -n 5 finger finger root bin daemon adm lp ?...y ......底下省略..... # 在这里鸟哥使用了 -p 这个参数来让您对于 -n 更有概念。一般来说,某些指令后面 # 可以接的 arguments 是有限制的,不能无限制的累加,此时,我们可以利用 -n # 来帮助我们将参数分成数个部分,每个部分分别再以指令来运行!这样就 OK 啦!^_^ [root@linux ~]# 范例四:同上,但是当分析到 lp 就结束这串指令? [root@linux ~]# cut -d':' -f1 < /etc/passwd | xargs -p -e'lp' finger finger root bin daemon adm ?... # 仔细与上面的案例做比较。也同时注意,那个 -e'lp' 是连在一起的,中间没有空白键。 # 上个例子当中,第五个参数是 lp 啊,那么我们下达 -e'lp' 后,则分析到 lp # 这个字符串时,后面的其他 stdin 的内容就会被 xargs 舍弃掉了!其实,在 man xargs 里面就有三四个小范例,您可以自行参考一下内容。 此外, xargs 真的是很好用的一个玩意儿!您真的需要好好的参详参详!
[root@linux ~]# tar -cvf - /home | tar -xvf -
上面这个例子是说:『我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是发送到 stdout;
经过管线后,将 tar -cvf - /home 发送给后面的 tar -xvf - 』。后面的这个 - 则是取用前一个指令的 stdout,
因此,我们就不需要使用 file 了!这是很常见的例子喔!注意注意!