linux下的移动和合并以及星点星那些破事

文章更新

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/

命令说明

  1. 视mv命令中第二个参数类型的不同(文件还是目录?),mv命令将文件重命名或将其移至一个新的目录中。
  2. 当第二个参数类型是文件时,mv命令完成文件重命名,此时,源文件只能有一个(也可以是源目录名),它将所给的源文件或目录重命名为给定的目标文件名。
  3. 当第二个参数是已存在的目录名称时,源文件或目录参数可以有多个,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,一个dir2dir1下有文件,有带.的文件,有不带扩展名的文件,也有隐藏的文件和目录

实例目录

首先,先说 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

实例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

实例3

我的结果是

cp -r dir1/. dir2/
cp -r dir1/* dir2/(这条的效果,我并没有亲自验证)

这俩个效果一样(待查)

cp dir1/. dir2/ 则什么都不会复制过去。

特别感谢 树莓派贴吧官方群 QQ群里的 萌萌哒 同学的大力支持,他亲自实践了好多内容,没有他就没有这篇文章的最终出炉。

参考文章

  1. Linux下目录的合并以及文件的覆盖
  2. linux实用命令之如何移动文件夹及文件下所有文件