什么是shell
shell 是一个命令语言解释器(command-language interpreter)。 拥有自己内建的 shell 命令集。此外,shell也能被系统中其他有效的Linux 实用程序和应用程序(utilities and application programs)所调用。
不论何时你键入一个命令,它都被Linux shell所解释。一些命令,比如打印当前工作目录命令(pwd), 是包含在Linux bash内部的(就象DOS的内部命令)。其他命令,比如拷贝命令(cp)和移动命令(rm), 是存在于文件系统中某个目录下的单独的程序。而对用户来说,你不知道(或者可能不关心) 一个命令是建立在shell内部还是一个单独的程序。
文件管理类命令
1,ls 查看文件和目录
语法: ls [-aAdfFhilRS] [文件或目录]
常用选项:
-a:显示所有文件,包括隐藏文件(以 . 开头的文件)
-l:详细列出文件的属性等信息
-d:仅列出目录本身,而不是列出目录内的文件数据
范例:
[root@foundation0 www]# cd /tmp/
[root@foundation0 tmp]# ls #查看目录/tmp中的文件
test1 test2
[root@foundation0 tmp]# ls -a #查看目录/tmp中的所有文件,包括隐藏文件
. .. .esd-1000 .font-unix .ICE-unix test1 test2 .Test-unix .X0-lock .X11-unix .XIM-unix
[root@foundation0 tmp]# ls -l #查看目录中的文件的详细信息
total 0
drwxr-xr-x. 2 root root 6 Sep 24 16:33 test1
drwxr-xr-x. 3 root root 18 Sep 24 16:33 test2
[root@foundation0 tmp]# ls -l -d #查看本目录/tmp的详细信息 ,可以简写成ls -ld
drwxrwxrwt. 12 root root 4096 Sep 24 16:56 .
2,cd 切换目录
常用的一些特殊目录:
. 代表当前目录
.. 代表上一层目录
- 代表前一个工作目录
~ 代表【目前用户身份】所在的自家目录
~account 代表 account 这个用户的自家家目录
范例:
[root@foundation0 ~]# cd /home/ # 进入/home目录
[root@foundation0 home]# cd . # .表示当前目录,所以还是在home目录
[root@foundation0 home]# cd .. # ..表示上一层目录,所以此时就进入到了/目录下
[root@foundation0 /]# cd ~ # ~表示当前用户的家目录,当前用户是root,所以进入目录/root/
[root@foundation0 ~]# cd ~xcp # ~account代表account这个用户的自家家目录,所以进入用户xcp的家目录/home/xcp/
[root@foundation0 xcp]# pwd #当前确实位于目录/home/xcp/
/home/xcp
[root@foundation0 xcp]# cd - # -表示前一个工作目录,我们之前位于目录/root/下,所以就进入了目录/root/
[root@foundation0 ~]# cd ../var/ #切换目录时可以写绝对路径也可以写相对路径
[root@foundation0 home]# pwd
/var
3,pwd 显示当前所在目录
选项:-P: 显示出真实路径,而非使用链接(link)路径。(大写的参数P)
范例:
[root@foundation0 home]# pwd #显示当前目录
/home
[root@foundation0 home]# cd /var/mail/
[root@foundation0 mail]# pwd #显示当前所在目录是/var/mail
/var/mail
[root@foundation0 mail]# pwd -P #加了选项-P结果却不一样了
/var/spool/mail
[root@foundation0 mail]# ls -l /var/mail #其实是因为/var/mail是一个链接文件,链接到/varspool/mail,所以加上-P就会显示真实目录
lrwxrwxrwx. 1 root root 10 Sep5 03:22 /var/mail -> spool/mail
4,touch 创建空文件
范例:
[root@foundation0 tmp]# touch 1.txt 2.txt 3.txt
[root@foundation0 tmp]# ls
1.txt 2.txt 3.txt
[root@foundation0 tmp]# ls -l
total 0 #这一行表示列出的文件大小之和,0表示全都是空文件。
-rw-r--r--. 1 root root 0 Sep 24 17:06 1.txt
-rw-r--r--. 1 root root 0 Sep 24 17:06 2.txt
-rw-r--r--. 1 root root 0 Sep 24 17:06 3.txt
[root@foundation0 tmp]#
5,mkdir 创建新目录
选项: -p:如果不存在父级目录,则按照需要递归创建目录,如果父级目录存在则也不报错。
范例:
[root@foundation0 ~]# cd /tmp/
[root@foundation0 tmp]# rm -rf *
[root@foundation0 tmp]# mkdir test1 #创建一个新目录
[root@foundation0 tmp]# mkdir test2/test3 #递归创建两个目录,结果系统提示没有目录test2
mkdir: cannot create directory ‘test2/test3’: No such file or directory
[root@foundation0 tmp]# mkdir -p test2/test3 #加了选项-p成功创建这两个目录
[root@foundation0 tmp]# ls
test1 test2
[root@foundation0 tmp]# ls test2
test3
6,cp 复制文件或目录
语法:cp [-adfilprsu] source(源文件或目录) destination(目的文件或目录)
or:cp [options] source1 source2 source3 ..... directory(目的目录)
常用选项:
-a :相当于 -pdr,归档备份(保存文档的所有原属性)
-f :为强制 (force) 的意思,若有重复或其他疑问时,不会询问使用者,而强制复制
-i :若目的文件(destination)已经存在时,在覆盖时会先询问是否真的覆盖
-p :连同文件的属性一起复制过去,而非使用默认属性
-r :递归持续复制,用于目录的复制行为
范例:
[root@foundation0 tmp]# cp /var/log/wtmp wtmp
[root@foundation0 tmp]# ls -l /var/log/wtmp wtmp
-rw-rw-r--. 1 root utmp 23424 Sep 24 15:41 /var/log/wtmp
-rw-r--r--. 1 root root 23424 Sep 24 17:30 wtmp
[root@foundation0 tmp]#
#在不加任何参数的情况下,文件的所属者会改变,权限也跟着改变了,连文件建立的时间也不一样了! 如果想要将文件的所有特性都一起复制过来,加上 选项-a 即可。
[root@foundation0 tmp]# cp /root/.bashrc bashrc
[root@foundation0 tmp]# cp -i /root/.bashrc bashrc
cp: overwrite ‘bashrc’? y
# 重复做两次拷贝,由于 /tmp 底下已经存在 bashrc 了,加上 选项-i ,则在覆盖前会询问使用者是否确定!可以按下 n 或者 y 。反过来说,如果不想要询问时,则加上 -f 来强制直接覆盖。
[root@foundation0 tmp]# cp /root/ /tmp/
cp: omitting directory ‘/root/’
[root@foundation0 tmp]# cp -r /root/ /tmp/
[root@foundation0 tmp]# ls
1.txt 2.txt 3.txt bashrc root wtmp
#如果我们复制的是目录,此时必须要加上 -r 这个选项才行
7,mv 移动文件与目录、文件重命名
范例:
[root@foundation0 ~]# cp .bashrc /tmp/bashrc
[root@foundation0 ~]# cd /tmp/
[root@foundation0 tmp]# mv bashrc test1/bashrc #将文件bashrc移动到目录/tmp/test1/中去
[root@foundation0 tmp]# cd test1
[root@foundation0 test1]# mv bashrc bashrc.bak #将文件bashrc更名为bashrc.bak
[root@foundation0 test1]# ls
bashrc.bak
[root@foundation0 test1]#
#其实在 Linux 底下还有个命令 rename ,该命令就是专门用来对文件或者目录进行重命名的。可以参阅 man rename 了解其更多的用法。
8,rm 删除文件或目录
常用选项:
-f :就是 force 的意思,强制移除
-i :互动模式,在删除前会询问使用者是否动作
-r :递归删除,常用在目录的删除
范例:
[root@foundation0 tmp]# rm test2 #删除目录必须要加选项-r
rm: cannot remove ‘test2’: Is a directory
[root@foundation0 tmp]# rm -ir test2 #删除时会询问是否确认删除
rm: remove directory ‘test2’? y
[root@foundation0 tmp]# rm -rf test1/ #加了选项-f直接强制删除目录以及里面所有文件
#其实rm命令系统内置了别名相当于‘rm -i’,所以就算不加选项-i系统也会提示再次确认,关于别名的用法在后面会进行说明。此外在实际环境中要习惯不用命令‘rm -rf’来删除文件,以防错写目录或者文件路径没有写全导致系统文件被误删。
Bash的工作特性
Bash,全称为Bourne-Again Shell。它是一个命令处理器,属于shell的一种,通常运行于文本窗口中,并能执行用户直接输入的命令。
关于Bash的工作特性,主要有以下几点:
1,命令执行状态返回值
在我们每次输入命令之后,系统都会把命令执行的状态结果保存在一个变量中,我们称这个变量是特殊变量,用$?来表示。
范例:
[root@foundation0 tmp]# mkdir test1
[root@foundation0 tmp]# rm test1/
rm: cannot remove ‘test1/’: Is a directory
[root@foundation0 tmp]# echo $?
1 # 非0表示执行过程中出现异常或非正常退出,范围是1-255
[root@foundation0 tmp]# touch 1.txt
[root@foundation0 tmp]# echo $?
0 # 0表示执行成功
[root@foundation0 tmp]#
2,命令行展开
~ 和 {}
~ :展开为对应用户的家目录。其实前面我们已经使用过,管理员root通过cd ~xcp进入到用户xcp的家目录
{} :在非引号内的内容中,如果用花括号包括,而且里面用逗号分隔(至少包含一个逗号,可以是空内容),这样花括号里的内容会被展开成用空格分开的一个列表,花括号前后可以紧随前缀和后缀(前后缀都是可选的)。
范例:
(1)在/tmp目录下创建文件a_c , a_d,b_c,b_d:
[root@foundation0 tmp]# touch {a,b}_{c,d}
[root@foundation0 tmp]# ls
a_c a_d b_c b_d
[root@foundation0 tmp]#
(2)在/tmp/mylinux目录下创建目录树:
通过命令行展开一步创建:
3,别名机制
(1)alias:命令alias可以直接查看当前系统定义的所有别名条目。
范例:
[root@foundation0 ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias mv='mv -i'
alias rm='rm -i'
[root@foundation0 ~]#
(2)alias 别名="原始命令 [选项]" :定义一项别名,选项可加可不加。
如需要使其永久生效可写入局部配置文件中:~/.bashrc(每个用户可自定义)
范例:
(3)unalias 别名 :撤销自定义的别名
范例:
[root@foundation0 ~]# alias ipconfig
alias ipconfig='ifconfig eno16777736'
[root@foundation0 ~]# unalias ipconfig
[root@foundation0 ~]# alias ipconfig
-bash: alias: ipconfig: not found
[root@foundation0 ~]#
4,shell引用
' ':强引用,变量替换不会进行
" ":弱引用,能够执行变量替换
` `:命令替换,引用命令的执行结果
$(命令):同样可以实现命令替换
范例:
[root@foundation0 ~]# echo '$PATH' # 强引用,变量没有被替换
$PATH
[root@foundation0 ~]# echo "$PATH" # 弱引用,执行变量替换
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@foundation0 ~]# echo `which ls` # 命令echo引用了``里的命令结果
alias ls='ls --color=auto' /usr/bin/ls
[root@foundation0 ~]# echo $(which touch) #命令echo引用了$()里的命令结果
/usr/bin/touch
[root@foundation0 ~]#
5,Bash补全
Bash补全的按键是<Tab>,可以实现命令与路径的补全。
注:参数的补全并非Bash自带功能,而是由/etc/bash_completion.d/下对应的脚本实现的。
命令补全:
shell程序在接收到用户执行命令的请求且分析完成之后,最左侧字符串将被当作命令去查找;
查找机制:
(1) 查找内部命令;
(2) 查找外部命令:
<1> 去$PATH变量所指定的各路径下,自左而右逐个搜索各目录下的文件名;
<2> 给定的打头的字符串如果能唯一标识某命令程序文件的文件名,则直接补全;
<3> 不能惟一标识,再击tab可给列表;
<4> 错误:没有任何命令可被此打头字符串标识。
范例:
[root@foundation0 ~]# firewall-<Tab><Tab> #不能惟一标识,再击tab可给列表
firewall-cmd firewall-config firewall-offline-cmd
[root@foundation0 ~]# firewall-
路径补全:
在起始路径的上级目录下,以对应路径下的打头字符串来逐一匹配上级目录下的每个文件:
惟一标识:tab补全;
不能惟一标识:tab, tab给出列表;
错误路径:没有响应。
范例:
[root@foundation0 ~]#ls /t<Tab> # 唯一补全结果会立即补全
[root@foundation0 ~]#ls /tmp/
[root@foundation0 ~]# vim /etc/sys<Tab><Tab> # 不能唯一标识结果需要按两下<Tab>给出列表
sysconfig/ sysctl.d/ system-release
sysctl.conf systemd/ system-release-cpe
[root@foundation0 ~]# vim /etc/sys
Bash除了以上5条特性之外还有很多特性,例如命令历史,Globbing,文件名通配,命令行快捷键,提供编程环境,Bash变量,输入输出重定向等等。
文件的元数据信息
linux系统中文件是由3个部分组成:
1,文件名——directory entry(也叫目录项)
2,数据——data(指的是文件中编辑保存的内容)
3,元数据——matedata(当你用ls -l命令列出的信息就是元数据,在linux、unix系统中,所有与文件相关的元数据都保存在一个叫做inode的结构中)
通过ls -l(或者ll)命令列出的信息有文件的类型、所有者的身份与对应的权限、链接数量、文件最后的ctime等等。
范例:
[root@foundation0 tmp]# ll 1.txt
-rw-r--r--. 1 root root 115 Sep 24 19:46 1.txt
对于文件1.txt:
第一列是-rw-r--r--, 其中第一个字符是"-",在缩写表中对应常规文件。后面的九个字符“rw-r--r--”表 示权限;
第二列是1 表示链接数,如果有硬链接到这个文件,这里的数值会+1,删除硬连接这里 会-1;
第三列是root 表示文件所有者是root;
第四列是root 表示文件所有组是root;
第五列是115 表示文件占用115字节
第六列是Sep 24 19:46 默认表示文件最后的ctime, change-time
第七列是1.txt 表示文件名
此外,我们还可以使用stat命令来查看文件更多的元数据信息:
[root@foundation0 tmp]# stat 1.txt
File: ‘1.txt’
Size: 115 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 1093845547 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2016-09-24 19:46:21.368240354 +0800
Modify: 2016-09-24 19:46:19.162240439 +0800
Change: 2016-09-24 19:46:19.162240439 +0800
Birth: -
[root@foundation0 tmp]#
对各项元数据的解释:
Size 表示文件的理论长度,单位是字节
Block 与 IO Block 的乘积是文件所占的实际大小,在linux下文件所占的空间分配,最小的单位是块(Bolck),而块的大小与块的数量,决定了文件实际占用的磁盘空间.
Device: 表示内核对该设备的编号
Inode: 是内核为每一个文件分配的标志
Links: 表示文件名指向的inode节点的数量
Access:(0755/-rwxr-xr-x) 表示了访问权限,以及文件类型
uid: 表示了文件所有者,包括了系统为所有者分配的数值id
gid: 表示了文件组,包括了系统为组分配的数值id
Context:环境,也叫上下文关系,在某些目录下至关重要,决定了该文件是否能被系统识别使用
最后就是三个时间戳了:
Access time: 访问时间,简写为atime,文件数据每次被阅读后所记录的时间
Modify time: 修改时间,mtime,文件内容数据被修改后记录的时间
Change time: 改动时间,ctime,文件的inode节点信息被改变后记录的时间
如何修改时间戳呢,可以用touch命令来实现:
语法:touch [options] file
选项:
-a:仅修改access time;
-m:仅修改modify time;
-t STAMP:指定一个任意时间
范例:
[root@foundation0 tmp]# touch 1.txt #不加任何参数表示把三个时间戳都改成当前时间
[root@foundation0 tmp]# stat 1.txt #三个时间都变成了当前时间
File: ‘1.txt’
Size: 115 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 1093845547 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2016-09-24 23:31:27.303718903 +0800
Modify: 2016-09-24 23:31:27.303718903 +0800
Change: 2016-09-24 23:31:27.303718903 +0800
Birth: -
[root@foundation0 tmp]# touch -a 1.txt #使用-a参数,修改访问时间
[root@foundation0 tmp]# touch -m -t 201608011001.20 1.txt #使用-m -t把时间改为指定的时间
[root@foundation0 tmp]# stat 1.txt #mtime已更改为上面指定的时间
File: ‘1.txt’
Size: 115 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 1093845547 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2016-09-24 23:32:21.721716802 +0800
Modify: 2016-08-01 10:01:20.000000000 +0800
Change: 2016-09-24 23:33:53.905713243 +0800
Birth: -
[root@foundation0 tmp]#
命令练习:
1,显示/var目录下所有以l开头,以一个小写字母结尾,且中间至少出现一位数字(可以有其它字符)的文件或目录:
[root@foundation0 tmp]# touch /var/like123321like
[root@foundation0 tmp]# ls -d /var/l*[[:digit:]]*[[:lower:]]
/var/like123321like
或者
[root@foundation0 tmp]# ls -d /var/l*[0-9]*[a-z]
/var/like123321like
2,显示/etc目录下 以任意一个数字开头 且以非数字结尾的文件或目录:
[root@foundation0 tmp]# touch /etc/{1..3}.txt
[root@foundation0 tmp]# mkdir /etc/{4..5}note
[root@foundation0 tmp]# ls -d /etc/[0-9]*[^0-9]
/etc/1.txt /etc/2.txt /etc/3.txt /etc/4note /etc/5note
3,显示/etc目录下,以非字母开头 后面跟了一个字母以及其他任意长度任意字符的文件或目录:
[root@foundation0 tmp]# ls -ld /etc/[^[:alpha:]][[:alpha:]]*
drwxr-xr-x. 2 root root 6 Sep 25 00:19 /etc/4note
drwxr-xr-x. 2 root root 6 Sep 25 00:19 /etc/5note
或者
[root@foundation0 tmp]# ls -dl /etc/[^a-z][a-z]*
drwxr-xr-x. 2 root root 6 Sep 25 00:19 /etc/4note
drwxr-xr-x. 2 root root 6 Sep 25 00:19 /etc/5note
[root@foundation0 tmp]# mkdir /etc/4NOTE #新创建一个第二个字符是大写字母的目录
[root@foundation0 tmp]# ls -dl /etc/[^a-z][a-z]* #不管是[a-z]还是[A-Z],结果并不区分大小写
drwxr-xr-x. 2 root root 6 Sep 25 00:19 /etc/4note
drwxr-xr-x. 2 root root 6 Sep 25 00:37 /etc/4NOTE
drwxr-xr-x. 2 root root 6 Sep 25 00:19 /etc/5note
4,在/tmp 目录下创建以tfile 开头,后跟当前日期和时间的文件,文件名形如:tfile-2016-05-27-09-32-22:
[root@foundation0 tmp]# touch tfile-`date +%Y-%m-%d-%H-%M-%S`
[root@foundation0 tmp]# ls tfile*
tfile-2016-09-25-00-53-04
5,复制/etc 目录下所有以p 开头 以非数字结尾的文件或目录到/tmp/mytest1目录中:
[root@foundation0 tmp]# mkdir mytest1 #复制多个文件到目录时,该目录必须已经存在。
[root@foundation0 tmp]# cp -r /etc/p*[^0-9] mytest1/
[root@foundation0 tmp]# ls !$
ls mytest1/
pam.d passwd- pki pm postfix prelink.conf.d profile protocols purple
passwd pinforc plymouth popt.d ppp printcap profile.d pulse python
6,复制/etc目录下所有以.d结尾的文件或目录至/tmp/mytest2目录中:
[root@foundation0 tmp]# mkdir mytest2
[root@foundation0 tmp]# cp -r /etc/*.d mytest2
7,复制/etc目录下所有以.d结尾的文件或目录至/tmp/mytest2目录中
[root@foundation0 tmp]# mkdir mytest3
[root@foundation0 tmp]# cp -r /etc/[l,m,n]*.conf /tmp/mytest3
附注:(常用通配符)
* :匹配任意长度的任意字符
?: 匹配任意单个字符
[ ]:匹配指定字符范围内的任意单个字符
[a-z] 不区分大小写 <--->[[:lower:]] 所有小写字母
[A-Z] 不区分大小写 <--->[[:upper:]] 所有大写字母
[0-9] [[:digit:]] 所有数字
[a-z0-9A-Z] [[:alnum:]] 所有字母和数字
[[:alpha:]] 所有大小写字符
[[:space:]] 空白字符
[[:punct:]] 特殊符号、标点符号
[^]:匹配指定字符范围外的任意单个字符;
如:非数字:[^0-9]