复制除“.txt”之外的目录中的所有文件,而不是替换现有文件

时间:2014-06-27 06:46:07

标签: shell

我必须将所有文件从源目录复制到目标目录,但是跳过所有扩展名为“.txt”的文件,如果文件已经存在于目标目录中,则不要替换该文件

例如

源目录

    /a/aone.js
    /a/atwo.js
    /b/bone.txt
    /b/btwo.js  

目标目录

    /a/atwo.js

那么它应该只复制

    /a/aone.js
    /b/btwo.js

并跳过“/a/atwo.js”,因为它已经存在于目标文件夹中 并跳过“/b/bone.txt”,因为它的扩展名为“.txt”

我试过这个命令,但这不起作用

 find /path/to/source/ \( ! -name "*.txt" \) -type f | cp -n /path/to/destination/ -R

 cp -n /path/to/source/*(!*.txt) /path/to/destination/ -R

2 个答案:

答案 0 :(得分:1)

假设你可以使用rsync,(vaz是详细的,存档和压缩 - 我相信其他选项都是不言自明的)

rsync -vaz --exclude "*.txt" /path/to/source/ /path/to/destination/

答案 1 :(得分:1)

为什么要让它变得困难。你走在正确的轨道上。一个简单的:

cp -an /path/to/source/*.[^t*] /path/to/destination

将从源复制所有文件,但扩展名以t开头的文件除外。它会这样做而不会覆盖目标中的现有文件。这假设文件没有多个点。如果是这样,那么将需要更多行代码。

以下将说明上述用法:

$ md tmp
$ md a
$ md b
$ touch a/a.{j,k,l,txt}

$ ls -1 a
a.j
a.k
a.l
a.txt

$ cp -an a/a*.[^t*] b

$ ls -1 b
a.j
a.k
a.l

使用cp,您必须匹配正确的目录深度。如果您有另一个介入目录,则只需添加一个额外的通配符。例如:

$ ls -1 dat/*/*.[^t*]
dat/a/a.j
dat/a/a.k
dat/a/a.l
dat/b/a.j
dat/b/a.k
dat/b/a.l

如果您的目录结构变得更复杂,请使用findrsync。两者都是出色的工具,rsync可以处理本地和网络传输。 cp是适合小型工作的合适工具,但如果需要更大的灵活性,那就抓住更大的锤子。