文章更新
1.201608017-初次成文,稍晚加入了关于. * 以及*.*的说明
为什么会有这篇文章
因为使用btsync,刚开始的时候,经常崩溃,然后每次重新安装,btsync就会放弃之前的同名目录,重新建一个文件夹,并在文件夹名字后面加上一个郁闷的(1)或者(2),因此就有很多闲置文件夹放在那占着空间。由于总担心会不小心覆盖错了文件,因此就想好好研究下linux下的文件移动和覆盖以及合并文件的问题。
方法1:使用cp命令
比如,有两个目录test和new,test目录下有目录和文件,new目录下有更改过的一些test下的目录和文件,以及一些新增的文件,现在对两个目录进行合并以及覆盖test下的旧文件
cp -fRap new/* test/
命令参数
- f 强制覆盖,不询问yes/no(-i的默认的,即默认为交互模式,询问是否覆盖)
- R 递归复制,包含目录
- a 做一个备份,这里可以不用这个参数,我们可以先备份整个test目录。该选项通常在拷贝目录时使用,它保留链接、文件属性,并递归地拷贝目录,其作用等于dpR选项的组合。
- p 保持新文件的属性不变。
- d 拷贝时保留链接。
- i 和f选项相反,在覆盖目标文件之前将给出提示要求用户确认。回答y时目标文件将被覆盖,是交互式拷贝。
- p 此时cp除复制源文件的内容外,还将把其修改时间和访问权限也复制到新文件中。
- r 若给出的源文件是一目录文件,此时cp将递归复制该目录下所有的子目录和文件。此时目标文件也必须为一个目录名。
需要说明的是,如用户指定的目标文件名是一个已存在的文件名,用cp命令拷贝文件后,这个文件就会被新拷贝的源文件覆盖。为防止用户出现这种意想不到的情况,建议在使用cp命令拷贝文件时,最好使用i选项。
命令实例
cp -r /usr/xu/ /usr/liu/ #将/usr/xu目录中的所有文件及其子目录拷贝到目录/usr/liu中。
cp -fRp new/* test/ #将new目录下的所有文件和目录复制到test目录下面
cp -r dir1 dir2 #dir2不存在,能将dir1下所有文件复制到dir2下
cp -r dir1/. dir2 #如果dir2目录已存在,则需要在dir1后面加上 /. 因为如果使用cp -r dir1 dir2,则也会将dir1目录复制到dir2中,明显不符合要求。
方法2:使用mv命令
命令格式
mv [选项(option)] 源文件或目录 目标文件或目录
如
mv webdata /bin/usr/
命令说明
- 视mv命令中第二个参数类型的不同(文件还是目录?),mv命令将文件重命名或将其移至一个新的目录中。
- 当第二个参数类型是文件时,mv命令完成文件重命名,此时,源文件只能有一个(也可以是源目录名),它将所给的源文件或目录重命名为给定的目标文件名。
- 当第二个参数是已存在的目录名称时,源文件或目录参数可以有多个,mv命令将各参数指定的源文件均移至目标目录中。在跨文件系统移动文件时,mv先拷贝,再将原有文件删除,而链至该文件的链接也将丢失。
参数说明
- i 交互方式操作。如果mv操作将导致对已存在的目标文件的覆盖,此时系统询问是否重写,要求用户回答”y”或”n”,这样可以避免误覆盖文件。
- f 禁止交互操作。mv操作要覆盖某个已有的目标文件时不给任何指示,指定此参数后i参数将不再起作用。
- r 指示mv将参数中列出的全部目录和子目录均递归地移动。
- b 若需覆盖文件,则覆盖前先行备份。
- u 若目标文件已经存在,则比较原文和目标文件哪个更新,如果源文件最近修改了,才会进行移动,否则就忽略。
命令实例
mv /usr/lib/* /zone #是将 /usr/lib 下所有文件移到 /zone 目录下。
mv /usr/lib/*.txt /zone #是将 /usr/lib 下以txt结尾的所有文件移到 /zone 目录下。
mv zhidao.txt baidu.txt #将文件zhidao.txt重命名为baidu.txt
mv log1.txt log2.txt log3.txt test3 #将文件log1.txt,log2.txt,log3.txt移动到目录test3中。
mv /usr/local/arm/arm/* /usr/local/arm/ #移动 /usr/local/arm/arm 目录下的全部东西到 /usr/local/arm/,而不是移动 /usr/local/arm/arm 这个目录到他处
mv -u dir1/* dir2/ #将dir1下的全部东西移动到dir2下,使用u参数是怕覆盖到新修改的文件,但是这个命令不会移动0字节的隐藏文件,或者0自己的可见文件。
关于. * 以及*.*
比如,下面这个问题
cp -r dir1/. dir2
cp -r dir1/* dir2
cp -r dir1/*.* dir2
这三个命令有区别么?再深一步,如果没有参数r,区别又是什么?
经过实践,大概缕清了头绪。
实例1
先上图,我建立了两个目录,一个dir1,一个dir2,dir1下有文件,有带.的文件,有不带扩展名的文件,也有隐藏的文件和目录

首先,先说 dir1/.,在这里 . 并不能代表全部文件。
如果使用 cp dir1/. dir2,会遇到 cp: omitting directory ‘dir1/.’ 的错误,但是进去dir2会发现,cp把隐藏的目录复制过去了,但是隐藏的文件,以及其他目录和文件都没有复制过去。 更正,什么都不会复制过去。
但是!我说但是,神奇的事情发生了,如果带着参数r,那么情况就完全不同了,具体请参考下面的 实例3。
使用rm -rf dir1/. ,会遇到 rm: refusing to remove ‘.’ or ‘..’ directory: skipping ‘dir1/.’ 的错误。并不会像cp命令那样,还删掉隐藏的文件夹或者其他什么内容。

实例2

rm -rf dir2/. 报错 rm -rf dir2/*.* 或者 rm -rf dir2/* 都没有删掉dir2下的隐藏目录 .hiddendir1
但是使用 rm -rf dir2/.* 却删掉了,虽然也遇到了错误
rm: refusing to remove ‘.’ or ‘..’ directory: skipping ‘dir2/.’
rm: refusing to remove ‘.’ or ‘..’ directory: skipping ‘dir2/..’
看来.*,在linux看来可以表示. 和 ..以及所有的隐藏目录和文件。
如果想彻底删掉目录下的所有文件(包括隐藏文件或隐藏目录),同时保留这个目录,目前看来是没有一步到位的方法,需要两条命令结合使用
rm -rf dir2/*
rm -rf dir2/.*
当然了,如果你连dir2都不要了,那么用一条命令就可以搞定 rm -rf dir2。
如果你在dir2目录下面,那么相应的命令就变成了
rm -rf ./*
rm -rf ./.*
是不是看着特别绕?想明白就好了。./* 并不包括隐藏目录和文件,因为只是恰巧.在linux既代表当前目录,又是隐藏文件的标识符,就比较有意思了。
实例3

我的结果是
cp -r dir1/. dir2/
cp -r dir1/* dir2/(这条的效果,我并没有亲自验证)
这俩个效果一样(待查)
cp dir1/. dir2/ 则什么都不会复制过去。
特别感谢 树莓派贴吧官方群 QQ群里的 萌萌哒 同学的大力支持,他亲自实践了好多内容,没有他就没有这篇文章的最终出炉。