开发者学堂课程【Linux企业运维实战 - 入门及常用命令:Linux文件通配符进阶及cp命令详解】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/550/detail/7603
Linux文件通配符进阶及cp命令详解
内容介绍:
一、上节回顾
二、练习
三、创建空文件和刷新时间
四、复制文件和目录cp
五、cp常用选项
六、练习
一、上节回顾
上节内容讲述了通配符,思考如何在当前目录里只显示隐藏文件?
输入ls -d.*
,显示如图
输入l.
后也一样,l.是个别名,alias l.= ‘ls -d .* --color=auto’
输入touch Desktop/.test
ls -d .*
如果想要显示当前目录下所有的隐藏文件包括每个文件夹下的隐藏文件,输入ls -R .*
发现下面文件..开头,进入到根目录中,因为.*包括..,而..是父目录。应该写为ls -R .[^.]*
想要显示所有隐藏文件,也可以输入 ls -a
,a显示所有隐藏文件以及不隐藏文件,再输入ls -a .[^.]*
默认进入到子目录里,如图再加入d,输入ls -ad .[^.]*
二、练习
1、显示/var目录下所有以l开头,以一个小写字母结尾,且中间出现至少一位数字的文件或目录
先创建文件,输入touch /data/la9ab
再输入ls /var/l*[[:digit]]*[[:lower:]]
显示/data/la9ab
2、显示/etc目录下以任意一位数字开头,且以非数字结尾的文件或目录
先创建文件,输入touch /data/9abc touch /data/9abc8
输入ls /etc/[0-9]*[^[:digit:]]
显示/data/9abc
3、显示/etc/目录下以非字母开头,后面跟了一个字母及其它任意长度任意字符的文件或目录
先创建文件,输入touch /data/3bxx
非字母开头:[^[a-zA-Z]]也可以写为[^[:alpha:]]
跟一个字母:[[:alpha:]]
输入ls /data/[^[:alpha:]][[:alpha:]]*
显示/data/3bxx /data/9abc /data/9abc8
4、显示/etc/目录下所有以rc开头,并后面是0-6之间的数字,其它为任意字符的文件或目录
输入ls /etc/rc[0-6]*
加上-d不会进入目录中,输入ls -d /etc/rc[0-6]*
显示如图
5、显示/etc目录下,所有以.d结尾的文件或目录
输入ls -d /etc/*.d
显示如图
6、显示/etc目录下,所有.conf结尾,且以m,n,r,p开头的文件或目录
输入ls -d /etc/[mnrp]*.conf
显示如图
7、只显示/root下的隐藏文件和目录
输入ls -d /root/.*
显示如图
8、只显示/etc下的非隐藏目录
只显示目录:*/ -d
输入ls /etc/[^.]*/ -d
显示如图
三、创建空文件和刷新时间
touch命令:
touch [OPTION]... FILE...
-a 仅改变atime和ctime
-m 仅改变mtime和ctime
-t [[CC]YY]MMDDhhmm[.ss]
指定atime和mtime的时间戳
-c 如果文件不存在,则不予创建
比如说输入touch f1
就会创建出f1空文件。
比如一个文件已经存在,touch不会覆盖,但是会刷新文件的时间,三个时间全刷新。输入ll /etc/hosts
touch /etc/hosts
ll /etc/hosts
输入touch -t 201910200830.50 /etc/hosts
stat /etc/hosts
显示如图修改了两个时间
-c意味着只用来刷新文件,输入touch -c f2
,f2是不存在的,输入ls不会创建就会显示f1,如果文件已经存在,比如touch -c f1,就会把时间做一次刷新,输入
touch -c f1
stat f1
显示如图
四、复制文件和目录cp
cp是copy简写,是外部命令,默认是一个别名,格式有以下三种语法:
cp [OPTION]...[-T]SOURCE DEST
cp [OPTION]... SOURCE...DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
cp SRC DEST
SRC是文件︰
如果目标不存在∶新建DEST,并将SRC中内容填充至DEST中
如果目标存在∶
如果DEST是文件∶将SRC中的内容覆盖至DEST中
基于安全,建议为cp命令使用-i选项
如果DEST是目录∶在DEST下新建与原文件同名的文件,并将SRC中内容填
充至新文件中
具体讲解:
第一种语法是cp加选项,选项可以多个,源source写在前,只能是一个,目标dest写在后,只能是一个,-[T]选项可有可无,只是复制单个目录或文件
第二种语法 源可以是多个,是把多个文件复制到文件夹里
第三种语法 是-t选项,文件夹在前,源在后,是把源的数据复制到目录中,一般不常用。
另外在cp命令复制时可能会遇到各种场景,如下
目标 源 |
不存在 |
存在且为文件 |
存在且为目录 |
一个文件 |
新建DEST,并将SRC中内容填充至DEST中 |
将SRC中的内容覆盖至DEST中 注意数据丢失风险!建议用-i选项 |
在DEST下新建与原文件同名的文件,并将SRC中内容填充至新文件中 |
多个文件 |
提示错误 |
提示错误 |
在DEST下新建与原文件同名的文件,并将原文件内容复制进新文件中 |
目录 须使用-r选项 |
创建指定DEST同名目录,复制SRC目录中所有文件至DEST下 |
提示错误 |
在DEST下新建与原目录同名的目录,并将SRC中内容复制至新目录中 |
比如
(1)第一种情况源是一个文件,目标不存在下用第一种语法,输入
cp /etc/hosts hosts.bak
效果是将etc/hosts复制,并改名为hosts.bak
再比较两者属性
ll /etc/hosts hosts.bak
发现大小完全一样,但是有些属性丢失
(2)目标存在且为文件时再来复制,输入
cp /etc/hosts hosts.bak
会显示是否覆盖 cp:overwrite ‘hosts.bak’? 覆盖输入y,回车默认不覆盖
此外须注意:
如果登录时是一个普通用户wang,现在把该文件复制到wang的家目录里,输入
cp /etc/hosts ~wang/
复制后wang的文件夹是存在的,但是没有写后面的文件名,意味着保留原来的名字hosts,复制完后查看属性,输入ll
,是root用户所拥有
再来复制motd文件到当前家目录中,当前家目录用.表示,文件名为hosts,输入cp /etc/motd ./hosts
,应该显示是否覆盖,但是结果显示没有权限,因为该文件是root用户所拥有
再来直接复制到家目录中并且不改名,输入cp /etc/motd .
,再复制文件motd,输入cp /etc/hosts motd
可以覆盖吗?
结果不显示,可以输入ll !*
查看,显示覆盖,因为motd文件最初是0字节,而现在是158字节
注意到在 root 用户下覆盖会询问是否覆盖,而 wang下则没有,是因为默认root用户下的cp不是真cp,是一个别名 alias cp= ‘cp -i’。而默认的cp命令是直接覆盖的,加-i会询问。
为了防止 wang 下的文件也被误覆盖,可以在 wang 的家目录下加别名 nano.bashrc,进入后在.bashrc下加入alias cp= ‘cp -i’
,最后存盘,输入 .bashrc
alias
别名生效
这时再想覆盖就会询问,输入cp /etc/issue motd
显示cp:overwrite ‘motd’?
(3)目标已经存在且为目录时,输入
cp /etc/hosts /data
,意味着把该文件复制到data目录中,并且保留该名称
(4)源是多个文件时用第二种语法,当目标不存在时,输入
cp /etc/issue /etc/hosts /data/f1
f1不存在,所以报错,结果显示
cp: target ‘/data/f1’ is not a directory
(5)当目标存在且为文件时,输入
cp /etc/issue /etc/hosts /data/fff
显示报错
cp:target ‘/data/fff’ is not a directory
(6)当目标存在且为目录时才能复制多个文件,输入
cp /etc/issue /etc/hosts /data/
,两个文件复制并保留原名称
输入ls /data
,显示data中已经有这两个新文件产生
2018-03-29.log f1 hosts hosts.bak issue
(7)复制目录时如果目标是文件,如下输入
cp /etc/sysconfig/ /data/issue
结果显示报错:cp:omitting directory ‘/etc/sysconfig/’
也可以写入一个新名字,如下dir不存在,输入
cp /etc/sysconfig/ /data/dir
,意味着把文件夹sysconfig复制到data下,命名成dir,相当于复制并改名,但是直接这样写会报错
cp:omitting directory ‘/etc/sysconfig/’提示忽略目录
因为cp命令默认不能复制文件夹,只是复制文件,要复制文件,必须跟-r属性,-r、在此是递归行为,复制该文件夹下的子文件或者目录等
输入
cp -r /etc/sysconfig/ /data/dir
再输入
ls /data
结果显示data下出现dir一个子目录
如果再次执行cp -r /etc/sysconfig/ /data/dir不会覆盖,会放到dir目录下作为子目录
输入ls /data/dir
查看
然而当第三次执行时会显示是否覆盖,如果想覆盖文件,我们无法输入一直输入y来确定覆盖,可以使用原始命令
\cp -r /etc/sysconfig/ /data/dir
此外-f属性不能覆盖,实际上是将原来文件删除再创建文件,而覆盖是文件内容发生变化但是文件属性不变
五、cp常用选项
-i:覆盖前提示 -n:不覆盖,注意两者顺序
-r,-R:递归复制目录及内部的所有内容
-a: 归档,相当于-dR --preserv=all
-d : --no-dereference --preserv=links不复制原文件,只复制链接名
--preserv[=ATTR_LIST]
mode:权限
ownership:属主属组
timestamp:
links
xattr
context
all
-p:等同--preserv=mode,ownership,timestamp
-v: --verbose
-f: --force
-u:--update 只复制源比目标更新文件或目标不存在的文件--backup=numbered目标存在,覆盖前先备份加数字后缀
具体讲解:
-a是一个综合选项,输入cp --help查看
-a可以用长格式的archive,作用等价于-dR --preserv=all功能的组合,r是递归,d是保留链接
什么是保留链接呢?
例如输入ll /etc/grub.conf
结果中显示快捷方式(软链接)/etc/grub.conf
现在拷贝该软链接复制到data目录下,那么复制后是软链接/etc/grub.conf还是软链接所指向的原始文件
../boot/grub/grub.conf呢?,
输入
cp /etc/grub.conf /data/
ll /data/
显示如图
显而易见,复制的是原始文件grub.conf,软链接应该仍然是浅蓝色
现在清除掉data目录数据,
输入
rm -rf /data/*
cp -d /etc/grub.conf /data/
ll /data/
显示结果中仍为浅蓝色grub.conf
所以-d保留链接实际上就是复制快捷方式,并不复制原始文件
preserv是保留的意思,可以保留一些特定属性,
例如mode,ownership,timestamps
mode是权限,ownership是所有者,timestamps是时间戳
在lrwxrwxrwx. 1 root root 22 Mar 30 11:34 grub.conf -> ../boot/grub/grub.conf中lrwxrwxrwx.是权限,root root 是所有者, Mar 30 11:34是时间戳
默认保留三个属性,如果保留以上三个属性,可以直接使用cp -p,-p选项相当于默认保留这三个
也可以保留其他属性,例如context上下文,links链接,xattr扩展属性等
-a选项全都保留,-p选项保留一部分,因此-a可以作为备份手段来实现,比如想备份etc,输入
cp -a /etc/ /data/etcbackup
ll /data
显示复制成功
另外在复制一些大的目录比如usr时,可以在复制时增加显示过程,添加v,输入
cp -av /usr /data/
-p属性只复制更新的文件,例如现在有一个文件f1,再复制到data下,输入
cp f1 /data/
如果修改了data下的f1内容,再次复制f1,输入
cp f1 /data/
就会将旧的内容复制到新内容上,而-u避免了复制旧内容
-backup选项在复制的目标已经存在时,会将旧的文件做备份,避免误覆盖,先来比较旧的f1和新的f1,输入
ll f1 /data/f1
显示data下的f1有17个字节,f1是0个字节,如果再输入
cp f1 /data/f1
会导致data下的f1成为0个字节,所以添加-u,输入
cp -u f1 /data/f1
ll f1 /data/f1
显示结果不会误覆盖,不会导致data下的f1被清零
再加上-backup选项会做备份,输入
cp --backup=numbered f1 /data/f1
显示结果询问是否覆盖,输入y覆盖后再来输入查看
ls /data
显示结果为f1 f1.~1~有备份
再输入ll /data
结果显示存在17个字节的旧文件f1.~1~
可以将--backup=numbered命令加入到别名中,省略复杂操作,输入
nano .bashrc
进入后在cp中添加
--backup=numbered
再输入..bashrc
生成
再输入
cp anaconda-ks.cfg /data/
cp anaconda-ks.cfg /data/
确定覆盖后输入ll /data
查看有备份anaconda-ks.cfg.~1~
六、练习
1、定义别名命令baketc,每天将/etc/目录下所有文件,备份到/data独立的子目录下,并要求子目录格式为backupYYYY-mm-dd ,备份过程可见
2、创建/data/rootdir目录,并复制/root下所有文件到该目录内,要求保留原有权限
(1)、要备份输入-a,过程可见输入v,注意如果写* 则则不包括etc中的隐藏文件
cp -av /etc/ /data/backup `data +%F`
复制成功,接下来定义成别名
alias backetc= ‘cp -av /etc/ /data/backup `data +%F`’
如果要存盘则需要放置到bashrc中
再来执行下效果,输入
rm -rf /data/*
backetc
可以实现别名
(2)保留原来属性用-a,输入
cp -a /root /data/rootdir
ll /data
查看data下存在rootdir
cp在复制特殊文件时存在问题,例如输入
ll /dev/zero
ll /dev/sda
在复制此类文件时不能直接复制,需要增加-a只保留属性信息,而不是复制硬盘里的内容,输入
cp -a /dev/sda /data
ll /data
进行复制,再比如复制zero文件,输入
cp -a /dev/zero /data/
ll /data/
面试题:
创建如下文件
touch file{1..100}.conf
要求把以上文件做备份,并且每个文件名后加bak后缀,cp命令无法完成,用到一个批量处理文件的命令rename,可以批量实现文件改名
再来创建一些不是以conf结尾的文件,输入
touch a.txt
Touch b.txt
现在只备份conf结尾的文件,输入
rename “conf” “conf.bak” file*
“conf” “conf.bak” 相当于要把conf字符串替换为conf.bak,对file开头的文件进行处理
若要删除,将.bak替换为空,输入
rename ‘.bak’ ‘ ’ file*