Linux 按文件列表拷贝文件到指定目录并保持原有的目录结构

需求说明

当需要拷贝多个文件并且需要保留源文件的目录树结构时, 如果源目录的文件比较纯净,没有其他相关的文件或目录时, 我们只需要执行

~$ #cp -r <源目录> <新目录>
~$ cp -r workspace/project workspace/Cpp
  • 1
  • 2

但是, 如果我们需要拷贝的文件所在的目录里包含了其他项目或程序的文件或目录, 那我们就不能这么干

比如,

  • 在 /etc或者/usr/local/bin下面有很多我们自己项目的相关配置文件和程序文件, 并且我们知道这些文件路径
  • 包含指定字符串的文件名, 比如 *.log
  • 我们自己制作或者我们比较感兴趣的其他厂商的 *.deb程序包(Ubuntu使用软件包)

针对自己的项目配置文件

我们可以新建一个文本文档, 里面把我们所关心的文件列出来

list.txt

/etc/app/app.cnf
/etc/app/conf.d/a.cnf
/etc/app/conf.d/b.cnf
/etc/app/conf.d/c.cnf
/etc/app/conf.d/d.cnf
  • 1
  • 2
  • 3
  • 4
  • 5

这样我们就可以通过使用 cat list.txt 获取到我们的文件路径列表

此时我们只需要使用

~$ cp --parent $(cat list.txt) .
  • 1

就可以将列表里面的所有文件按照原有的目录树结构拷贝到当前目录(或者使用其他目录)

针对包含指定字符串的文件名我们可以用 find 命令获取到文件列表

~$ find /opt/ros/ -name *.a
/opt/ros/kinetic/lib/liboctomath.a
/opt/ros/kinetic/lib/libcsm-static.a
/opt/ros/kinetic/lib/liboptions.a
/opt/ros/kinetic/lib/libegsl.a
/opt/ros/kinetic/lib/liboctomap.a
~$
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后, 嘿嘿

~$ cp --parent $(find /opt/ros -name *.a) .
  • 1

这不就都按照源目录结构拷贝到当前目录了嘛

针对.deb包的文件列表, 我们也有命令可以获取到路径列表

~$ dpkg -L mysql-server-5.7 
/etc
/etc/mysql
/etc/mysql/mysql.conf.d
/etc/mysql/mysql.conf.d/mysqld_safe_syslog.cnf
/etc/mysql/mysql.conf.d/mysqld.cnf
/etc/mysql/debian-start
/etc/mysql/mysql.cnf
/etc/apparmor.d
/etc/apparmor.d/usr.sbin.mysqld
/etc/logrotate.d
/etc/logrotate.d/mysql-server
/etc/init.d
/etc/init.d/mysql
/etc/logcheck
/etc/logcheck/ignore.d.server
/etc/logcheck/ignore.d.server/mysql-server-5_7
/etc/logcheck/ignore.d.workstation
/etc/logcheck/ignore.d.workstation/mysql-server-5_7
/etc/logcheck/ignore.d.paranoid
/etc/logcheck/ignore.d.paranoid/mysql-server-5_7
/etc/init
/etc/init/mysql.conf
~$ 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

这个时候我们就可以… -_- 嘿嘿嘿 , 你懂的