COPY命令的秘密

COPY 命令:

大家肯定都知道
COPY命令的主要作用是复制文件,其实它还有个妙用。就是可以将每个同类型或不同类型的文件合并。如果将一些不同类型的文件合并起来,就可以起到隐藏隐私的作用,
  一,准备加密条件
  准备一个EXE,或者是图片的文档,和一个TXT文档,要求用同一文件名,并且在同一目录下
  这里我用hello.jpg和hello.txt,保存为jpg,保存后我给他命名为sky,我现在已经把这两个文件当到D盘的根目录下了
  二,进行加密工作
  准备工作做好了进入CMD
使用CMD进入需要合并的文件的目录下,这里我把文件都放到了D盘根目录下,所以只进到D盘就可以了。呵呵不好意思
  近到目录下输入: copy hello.jpg/b + hello.txt/a sky.gif
  看到了吗复制成功了,合并后的文件我给他命名为SKY了,现在大家看看效果,看上去没有什么区别,但是我们记事本打开看看就不同了
  看到了吧,最下面的那些内容是HELLO.txt里的内容,是不是很有趣呀,这种方法是不是一种隐藏自己隐私的好方法呢。
  补充内容:
  copy c:\srv.exe \ip\***$ 意思
是复制srv.exe到对方IP下的***下
  copy \ip\***$\srv.exe c:\
意思是复制对方***i.exe文件至本地c:\
  还有上面说的hello.txt文件里面要空头三排 /b指二进制文件,
/a指ASCLL格式文件

Copy命令可以实现不同Oracle数据库间的数据的复制,也是可以实现同一数据库的数据复制,其性能表现和导入/导出相同。

Dockerfile
中提供了两个非常相似的命令 COPY 和
ADD,本文尝试解释这两个命令的基本功能,以及其异同点,然后总结其各自适合的应用场景。

开始

  // 描述:

根据9i文档,说Copy命令未来会不支持,但实际上Oracle
11g仍然支持Copy命令,只是未写入11g的文档里,未来12C不知道还支不支持。

Build 上下文的概念

在使用
docker build 命令通过 Dockerfile 创建镜像时,会产生一个 build
上下文(context)。所谓的 build 上下文就是 docker build 命令的 PATH 或 URL
指定的路径中的文件的集合。在镜像 build
过程中可以引用上下文中的任何文件,比如我们要介绍的 COPY 和 ADD
命令,就可以引用上下文中的文件。

默认情况下
docker build -t testx . 命令中的 . 表示 build
上下文为当前目录。当然我们可以指定一个目录作为上下文,比如下面的命令:

$ docker
build -t testx /home/nick/hc

我们指定
/home/nick/hc 目录为 build 上下文,默认情况下 docker
会使用在上下文的根目录下找到的 Dockerfile 文件。

COPY 和
ADD 命令不能拷贝上下文之外的本地文件

对于 COPY
和 ADD
命令来说,如果要把本地的文件拷贝到镜像中,那么本地的文件必须是在上下文目录中的文件。其实这一点很好解释,因为在执行
build 命令时,docker 客户端会把上下文中的所有文件发送给 docker
daemon
。考虑 docker 客户端和 docker daemon
不在同一台机器上的情况,build 命令只能从上下文中获取文件。如果我们在
Dockerfile 的 COPY 和 ADD
命令中引用了上下文中没有的文件,就会收到类似下面的错误:

图片 1


WORKDIR 协同工作

WORKDIR
命令为后续的 RUN、CMD、COPY、ADD 等命令配置工作目录。在设置了 WORKDIR
命令后,接下来的 COPY 和 ADD 命令中的相对路径就是相对于 WORKDIR
指定的路径。比如我们在 Dockerfile 中添加下面的命令:

WORKDIR
/app
COPY checkredis.py .

然后构建名称为
testx 的容器镜像,并运行一个容器查看文件路径:

图片 2

checkredis.py
文件就是被复制到了 WORKDIR /app 目录下。

csv 文件的内容:

    将一个或多个文件从一个位置复制到另一个位置。

Copy也有明显的缺点,Copy只支持五种数据类型,Char,Date,Long,Number,Varchar2,8i之后Oracle数据库新增的数据类型都不支持。

COPY 命令的简单性

如果仅仅是把本地的文件拷贝到容器镜像中,COPY
命令是最合适不过的。其命令的格式为:
COPY <src>
<dest>

除了指定完整的文件名外,COPY
命令还支持 Go 风格的通配符,比如:

COPY
check* /testdir/          # 拷贝所有 check 开头的文件
COPY check?.log /testdir/      # ? 是单个字符的占位符,比如匹配文件
check1.log

对于目录而言,COPY
和 ADD
命令具有相同的特点:只复制目录中的内容而不包含目录自身。比如我们在
Dockerfile 中添加下面的命令:

WORKDIR
/app
COPY nickdir .

其中
nickdir 目录的结构如下:

图片 3

重新构建镜像
testx,运行一个容器并查看 /app 目录下的内容:

图片 4

这里只有
file1 和 file2,少了一层目录 nickdir。如果想让 file1 和 file2 还保存在
nickdir 目录中,需要在目标路径中指定这个目录的名称,比如:

WORKDIR
/app
COPY nickdir ./nickdir

COPY
命令区别于 ADD 命令的一个用法是在 multistage 场景下。
关于 multistage
的介绍和用法请参考笔者的《Dockerfile 中的
multi-stage》一文。在
multistage 的用法中,可以使用 COPY
命令把前一阶段构建的产物拷贝到另一个镜像中,比如:

FROM golang:1.7.3
WORKDIR /go/src/github.com/sparkdevo/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk –no-cache add ca-certificates
WORKDIR /root/
COPY –from=0 /go/src/github.com/sparkdevo/href-counter/app .
CMD [“./app”]

这段代码引用自《Dockerfile
中的
multi-stage》一文,其中的
COPY 命令通过指定 –from=0
参数,把前一阶段构建的产物拷贝到了当前的镜像中。

id    name    departno    age
1    gao    10    30
2    jian    11    35
3    tom    11    30

    ### 注意:如果想复制文件夹,请使用 XCOPY 。

使用方法:

ADD 命令还可以干其它事情

ADD
命令的格式和 COPY 命令相同,也是:
ADD
<src> <dest>

除了不能用在
multistage 的场景下,ADD 命令可以完成 COPY
命令的所有功能,并且还可以完成两类超酷的功能:

  • 解压压缩文件并把它们添加到镜像中
  • 从 url
    拷贝文件到镜像中

当然,这些功能也让
ADD 命令用起来复杂一些,不如 COPY 命令那么直观。

解压压缩文件并把它们添加到镜像中
如果我们有一个压缩文件包,并且需要把这个压缩包中的文件添加到镜像中。需不需要先解开压缩包然后执行
COPY 命令呢?当然不需要!我们可以通过 ADD 命令一次搞定:

WORKDIR
/app
ADD nickdir.tar.gz .

这应该是
ADD 命令的最佳使用场景了!

从 url
拷贝文件到镜像中

这是一个更加酷炫的用法!但是在
docker
官方文档的最佳实践中却强烈建议不要这么用!!docker
官方建议我们当需要从远程复制文件时,最好使用 curl 或 wget 命令来代替 ADD
命令。原因是,当使用 ADD 命令时,会创建更多的镜像层,当然镜像的 size
也会更大(下面的两段代码来自 docker 官方文档):

ADD
/usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all

如果使用下面的命令,不仅镜像的层数减少,而且镜像中也不包含
big.tar.xz 文件:

RUN mkdir
-p /usr/src/things \
    && curl -SL \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all

好吧,看起来只有在解压压缩文件并把它们添加到镜像中时才需要
ADD 命令!

导入前:

  // 语法:

1.首先确保TNS里记录了源Instance和目标Instance的连接信息;

加速镜像构建的技巧

在使用 COPY
和 ADD 命令时,我们可以通过一些技巧来加速镜像的 build
过程。比如把那些最不容易发生变化的文件的拷贝操作放在较低的镜像层中,这样在重新
build 镜像时就会使用前面 build
产生的缓存。比如笔者构建镜像时需要用到下面几个文件:

图片 5

其中
myhc.py 文件不经常变化,而 checkmongo.py、checkmysql.py 和 checkredis.py
这三个文件则经常变化,那么我们可这样来设计 Dockerfile 文件:

WORKDIR
/app
COPY myhc.py .
COPY check* ./

让 COPY
myhc.py . 单独占据一个镜像层,当 build 过一次后,每次因
checkmongo.py、checkmysql.py 和 checkredis.py 这三个文件变化而导致的重新
build 都不会重新 build COPY myhc.py . 镜像层:

图片 6

如上图所示,第二步和第三步都没有重新
build 镜像层,而是使用了之前的缓存,从第四步才开始重新 build
了镜像层。当文件 size
比较大且文件的数量又比较多,尤其是需要执行安装等操作时,这样的设计对于
build 速度的提升还是很明显的。所以我们应该尽量选择能够使用缓存的
Dockerfile 写法。

postgres=# select a.relpages, a.reltuples, a.relfilenode,a.reltype,b.typname from pg_class a, pg_type b where a.relname like 'gaotab%' and a.reltype=b.oid;
 relpages | reltuples | relfilenode | reltype | typname 
----------+-----------+-------------+---------+---------
(0 rows)

postgres=# 

     copy [/a] [/b] [/d] [/v] [/n] [/z] [/y
| /-y] <source> [/a] [/b] [<source> [/a] [/b] [+
…]] [<destination> [/a] [/b]]
 

2.运行SQL * Plus(无需连接具体的Instance)

总结

当第一次看到 COPY
和 ADD 命令时不免让人感到疑惑。但分析之后大家会发现 COPY
命令是为最基本的用法设计的,概念清晰,操作简单。而 ADD 命令基本上是 COPY
命令的超集(除了 multistage 场景),可以实现一些方便、酷炫的拷贝操作。ADD
命令在增加了功能的同时也增加了使用它的复杂度,比如从 url
拷贝压缩文件时弊大于利。希望本文能够解去大家对 Dockerfile 中 COPY 和 ADD
命令的疑惑。

Linux公社的RSS地址:

本文永久更新链接地址

图片 7

导入之前,必须要建立好表的结构

  //  参数:

sqlplus /nolog

postgres=# create table gaotab(id integer,name varchar(20),departno integer,age integer);
CREATE TABLE
postgres=# 
postgres=# 
postgres=# COPY gaotab from '/soft/test.csv' with csv header;COPY 3
postgres=# select * from gaotab;
 id | name | departno | age 
----+------+----------+-----
  1 | gao  |       10 |  30
  2 | jian |       11 |  35
  3 | tom  |       11 |  30
(3 rows)

postgres=# 

    /a(ASCII):

3.运行Copy命令

导入已经成功

      –> 表示一个ASCII文本文件。  

Copy命令的语法:

导入后再看:

    /b(Binary):

COPY {FROM database | TO database | FROM database TO database}
{APPEND|CREATE|INSERT|REPLACE} destination_table [(column, column,
column, …)]
USING query

postgres=# select a.relpages, a.reltuples, a.relfilenode,a.reltype,b.typname from pg_class a, pg_type b where a.relname like 'gaotab%' and a.reltype=b.oid;
 relpages | reltuples | relfilenode | reltype | typname 
----------+-----------+-------------+---------+---------
        0 |         0 |       16384 |   16386 | gaotab
(1 row)

postgres=# 



postgres=# analyze gaotab;
ANALYZE
postgres=# select a.relpages, a.reltuples, a.relfilenode,a.reltype,b.typname from pg_class a, pg_type b where a.relname like 'gaotab%' and a.reltype=b.oid;
 relpages | reltuples | relfilenode | reltype | typname 
----------+-----------+-------------+---------+---------
        1 |         3 |       16384 |   16386 | gaotab
(1 row)

postgres=# 

      –> 表示一个二进制文件。

where database has the following syntax:

[作者:技术者高健@博客园
 mail: luckyjackgao@gmail.com ]

    /d(Decrpyted):

username[/password]@connect_identifier

结束

      –> 允许将复制的加密文件保存为目标位置的解密文件。

Copies data from a query to a table in a local or remote database. COPY
supports the following datatypes:

    /v(Verify):     

CHAR

      –> 验证是否正确写入了新文件。
      –> 如果无法验证写入操作,则会显示错误消息。
尽管复制时很少出现录制错误,但可以使用/v 验证是否已正确录制关键数据。
         ### 注意:/v
命令行选项也会降低复制命令的速度,因为必须检查磁盘上记录的每个扇区。

DATE

    /n:

LONG

       
–>
在复制名称长度超过八个字符的文件或文件扩展名超过三个字符的文件时,请使用短文件名。

NUMBER

    /z:

VARCHAR2

      –>
以可重新启动的模式复制网络文件。

Example:

      –>
如果在复制阶段连接丢失(例如,如果服务器脱机会断开连接),则在重新建立连接后将继续复制
/z。 /z 还显示为每个文件完成的复制操作的百分比。

  1. copy from user1/password1@source_instance to user2/password2@dest_instance create emp2 using select * from emp;  

    /y /-y:
      –> 如果在COPYCMD环境变量中预设了 /y,则可以在命令行使用
/-y 覆盖此设置。
默认情况下,除非在批处理脚本中执行复制命令,否则在替换此设置时会提示您。  

上边的命令会从source_instance中把emp数据拷贝到dest_instance中的emp2表。

  //
注意:

数据库内的复制,也可以使用Copy命令,Example:

–> 要复制目录的所有文件和子目录,请使用xcopy命令。

  1. copy from scott/password@ptian to scott/password@ptian create emp2 using select * from emp;  

–> 您可以复制使用文件结束符(CTRL +
Z)的ASCII文本文件来指示文件的结尾。

这就有点类似于CREATE TABLE empx AS (SELECT * FROM emp);
根据Tom的说法,Copy
的效率可能会比CREATE TABLE … AS …(数据库间的复制也可以使用Create
table…as,通过database
Link)差,因为Copy是把数据从一个Instance拷贝到sqlplus,再从sqlplus插入另外一个Instance。

–>
要附加文件,请为Destination指定单个文件,为Source指定多个文件(使用通配符或File1

而CREATE TABLE … AS
…是把一个数据库的数据直接插入到第二个数据库,所以效率会高一些。

  • File2 + File3格式)。

Copy 命令的四种模式

–> 可以将设备名称替换为一次或多次出现的源或目标。

*
replace子句指定了被创建的表名。如果目标表已存在,则删除并用包含复制数据的表替代。若不存在,则创建目标表。
*
使用create子句可避免覆盖已存在的表。若目标表已存在,则copy报告一个错误;若不存在,则创建目标表。
*
insert插入数据到已存在的表。将查询到的行插入到目标表,如果目标表不存在,copy返回错误。当使用insert时,using子句必须为目标表的每个列选择对应的列。
* append是将查询到的行插入到目标表。如果不存在,则创建目标表并插入。

–> 当Destination是设备(例如,Com1或Lpt1)时,/b
以二进制模式将数据复制到设备。 在二进制模式下,copy /b 将所有字符
   (包括特殊字符,如CTRL + C,CTRL + S,CTRL +
Z和ENTER)复制到设备作为数据。
但是,如果省略/b,则数据将以ASCII模式复制到设备。
     在ASCII模式下,特殊字符可能会导致文件在复制过程中合并。

其他说明

–>
如果未指定目标文件,则会创建与原始文件具有相同名称,修改日期和修改时间的副本。
新副本存储在当前驱动器的当前目录中。
   
 如果源文件位于当前驱动器和当前目录中,并且您没有为目标文件指定其他驱动器或目录,则copy命令将停止并显示以下错误消息:

如果copy命令比较长,可以在分行时每行末尾必须有续行符(-),最后一行不加。


  1. copy from scott/welcome@ptian –  
  2. to scott/welcome@ptian-  
  3. create empy-  
  4. using select * from emp-  
  5. where rownum = 1  

C:\Users\Administrator>copy a.txt
文件无法自身复制。

已复制 0 个文件。

–>
如果在Source中指定了多个文件,则copy会使用Destination中指定的文件名将它们全部合并到一个文件中。
除非使用 /b 选项,否则复制假定组合文件是ASCII文件。

–> 复制不会复制0字节长的文件。 使用xcopy复制这些文件。

–>
如果要在不修改文件的情况下将当前时间和日期分配给文件,请使用以下语法:


copy /b <Source> +,,

### “逗号” 表示省略了 Destination 参数

  //
实例:

**//

在当前目录中简单的复制:**

C:\Users\Administrator\cmd>echo a
> a.txt

 

C:\Users\Administrator\cmd>copy a.txt b.txt
已复制 1 个文件。

 

C:\Users\Administrator\cmd>dir
驱动器 C 中的卷是 Windows10
卷的序列号是 0D7B-113B

 

C:\Users\Administrator\cmd 的目录

 

2018-08-15 10:41 <DIR> .
2018-08-15 10:41 <DIR> ..
2018-08-15 10:41 4 a.txt
2018-08-15 10:41 4 b.txt
2 个文件 8 字节

2 个目录 19,742,240,768 可用字节

 

**//

把其他目录中的文件复制到当前目录中来:**

C:\Users\Administrator\cmd>copy d:\c.txt
已复制 1 个文件。

C:\Users\Administrator\cmd>dir
驱动器 C 中的卷是 Windows10
卷的序列号是 0D7B-113B

C:\Users\Administrator\cmd 的目录

2018-08-15 10:50 <DIR> .
2018-08-15 10:50 <DIR> ..
2018-08-15 10:49 4 a.txt
2018-08-15 10:49 4 b.txt
2018-08-15 10:27 0 c.txt
3 个文件 8 字节
2 个目录 19,739,402,240 可用字节

C:\Users\Administrator\cmd>

 

**//

把当前目录中的文件复制到其他目录中去:**

C:\Users\Administrator\cmd>copy a.txt d:\Lofter\

已复制 1 个文件。

 

// 合并文本文件:

C:\Users\Administrator\cmd>copy a.txt + b.txt c.txt
a.txt
b.txt
已复制 1 个文件。

C:\Users\Administrator\cmd>dir
驱动器 C 中的卷是 Windows10
卷的序列号是 0D7B-113B

C:\Users\Administrator\cmd 的目录

2018-08-15 11:00 <DIR> .
2018-08-15 11:00 <DIR> ..
2018-08-15 10:49 4 a.txt
2018-08-15 10:49 4 b.txt
2018-08-15 11:00 9 c.txt
3 个文件 17 字节

2 个目录 19,740,422,144 可用字节

 

// 合并二进制文件:

C:\Users\Administrator\cmd>copy /b d:\cloudmusic\1.mp3 +
d:\cloudmusic\2.mp3 3.mp3
d:\cloudmusic\1.mp3
d:\cloudmusic\2.mp3
已复制 1 个文件。

### 虽然可以合并,但是合并后的这个 3.mp3
文件并不能打开。所以好像没什么作用啊!
###
### 警告:

### 如果组合二进制文件,由于内部格式化,生成的文件可能无法使用。

 

// 复制远程主机上的共享文件。

C:\Users\Administrator\cmd>copy
\\172.17.161.253\软件\2345\2345minipack.ini /z /v
覆盖 C:\Users\Administrator\cmd\2345minipack.ini 吗? (Yes/No/All):
y

100% 已复制 已复制 1 个文件。

 

**//

还有一个高级的功能就是可以隐藏文本文件**

C:\Users\Administrator\cmd>copy 1.mp3 /b + a.txt /a 1a.mp3
1.mp3
a.txt
已复制 1 个文件。

###

把音频或图片文件跟文本文件合并在一起后,用记事本打开,文本的内容可以在记事本的最后看到。

 

 

 

相关文章