Linux系统中的find命令和xargs命令详解[技巧/资料]

本文最后更新于2014年6月26日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

在Linux下使用md5sum递归生成整个目录的MD5值
今天要用使用md5sum操作目录,发现它还不支持递归操作,网上有人提出用脚本,其实不用那么麻烦的。
一行命令就搞定了:
find ./ -type f -print0 | xargs -0 md5sum > ./my.md5
检查也很简单:
md5sum -c my.md5
#找到文件夹中比all.log.3新的文件然后将其打包
$ find -depth -newer all.log.3 -type f -exec tar czf log.tgz {} ;#将文件夹中所有的目录打包并压缩

$ find -type d --maxdepth 1 -exec tar czf website_info.tgz {} ;
$ find -type d --maxdepth 1 | xargs tar czf website_info.tgz

查找最近发生变化的php文件

find . -type f -name '*.php' -mtime -7

-type f 表示搜索正常的一般文件   -mtime -7 表示7*24小时内修改的文件

查找文件中是否存在疑似代码

find . -type f -name '*.php' | xargs grep -l "eval *(" --color

(*代表任意个空格)

find . -type f -name '*.php' | xargs grep -l "base64_decode *(" --color
find . -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color

注解:很多命令不支持管道传递参数,而实际上又需要这样,所以就用了xargs命令,这个命令可以用来管道传递参数;grep -l表示只包含某个字符串的文件名,如果去掉-l则会显示匹配特定字符串的行内容

比较代码文件

这种情况需要有一份干净的代码,这份代码和正在使用的代码进行比较。例如:

diff -r wordpress-clean/ wordpress-compromised/ -x wp-content

上面的例子是比较wordpress-clean/ 和wordpress-comprised/两个目录,并且目录里面的wp-content/子目录不比较。


find / ! -path "/usr/share/*" ! -path "/usr/lib/*" ! -path "/root/.pyenv/*" -regex ".*.sh$|.*.pl$|.*.py$|.*.conf$|.*.cnf$|.*.ini$|.*/..*history$|.*/..*pass.*" -print | zip pack.zip -@

  • find
[root@www ~]# find [PATH] [option] [action]
选项与参数:
1. 与时间有关的选项:共有 -atime, -ctime 与 -mtime ,以 -mtime 说明
   -mtime  n :n 为数字,意义为在 n 天之前的‘一天之内’被更动过内容的档案;
   -mtime +n :列出在 n 天之前(不含 n 天本身)被更动过内容的档案档名;
   -mtime -n :列出在 n 天之内(含 n 天本身)被更动过内容的档案档名。
   -newer file :file 为一个存在的档案,列出比 file 还要新的档案档名

范例一:将过去系统上面 24 小时内有更动过内容 (mtime) 的档案列出
[root@www ~]# find / -mtime 0

# 那个 0 是重点!0 代表目前的时间,所以,从现在开始到 24 小时前,
# 有变动过内容的档案都会被列出来!那如果是三天前的 24 小时内?
# find / -mtime 3 有变动过的档案都被列出的意思!

范例二:寻找 /etc 底下的档案,如果档案日期比 /etc/passwd 新就列出

[root@www ~]# find /etc -newer /etc/passwd
# -newer 用在分辨两个档案之间的新旧关系是很有用的!

时间参数真是挺有意思的!我们现在知道 atime, ctime 与 mtime 的意义,如果你想要找出一天内被更动过的档案名称, 可以使用上述范例一的作法。但如果我想要找出‘4天内被更动过的档案档名’呢?那可以使用‘ find /var -mtime -4 ’。那如果是‘4天前的那一天’就用‘ find /var -mtime 4 ’。有没有加上‘+, -’差别很大喔!我们可以用简单的图示来说明一下:

图5.2.1、find 相关的时间参数意义
图中最右边为目前的时间,越往左边则代表越早之前的时间轴啦。由图5.2.1我们可以清楚的知道:

  • +4代表大于等于5天前的档名:ex> find /var -mtime +4
  • -4代表小于等于4天内的档案档名:ex> find /var -mtime -4
  • 4则是代表4-5那一天的档案档名:ex> find /var -mtime 4

非常有趣吧!你可以在 /var/ 目录下搜寻一下,感受一下输出档案的差异喔!再来看看其他 find 的用法吧!

选项与参数:
3. 与档案权限及名称有关的参数:
    -name filename:搜寻档案名称为 filename 的档案;
    -size [+-]SIZE:搜寻比 SIZE 还要大(+)或小(-)的档案。这个 SIZE 的规格有:
                   c: 代表 byte, k: 代表 1024bytes。所以,要找比 50KB
                   还要大的档案,就是‘ -size +50k ’
    -type TYPE    :搜寻档案的类型为 TYPE 的,类型主要有:一般正规档案 (f),
                   装置档案 (b, c), 目录 (d), 连结档 (l), socket (s),
                   及 FIFO (p) 等属性。
    -perm mode  :搜寻档案权限‘刚好等于’ mode 的档案,这个 mode 为类似 chmod
                 的属性值,举例来说, -rwsr-xr-x 的属性为 4755 !
    -perm -mode :搜寻档案权限‘必须要全部囊括 mode 的权限’的档案,举例来说,
                 我们要搜寻 -rwxr--r-- ,亦即 0744 的档案,使用 -perm -0744,
                 当一个档案的权限为 -rwsr-xr-x ,亦即 4755 时,也会被列出来,
                 因为 -rwsr-xr-x 的属性已经囊括了 -rwxr--r-- 的属性了。
    -perm +mode :搜寻档案权限‘包含任一 mode 的权限’的档案,举例来说,我们搜寻
                 -rwxr-xr-x ,亦即 -perm +755 时,但一个档案属性为 -rw-------
                 也会被列出来,因为他有 -rw.... 的属性存在!

范例五:找出档名为 passwd 这个档案
[root@www ~]# find / -name passwd
# 利用这个 -name 可以搜寻档名啊!

范例六:找出 /var 目录下,档案类型为 Socket 的档名有哪些?
[root@www ~]# find /var -type s
# 这个 -type 的属性也很有帮助喔!尤其是要找出那些怪异的档案,
# 例如 socket 与 FIFO 档案,可以用 find /var -type p 或 -type s 来找!

范例七:搜寻档案当中含有 SGID 或 SUID 或 SBIT 的属性
[root@www ~]# find / -perm +7000
# 所谓的 7000 就是 ---s--s--t ,那么只要含有 s 或 t 的就列出,
# 所以当然要使用 +7000 ,使用 -7000 表示要含有 ---s--s--t 的所有三个权限,
# 因此,就是 +7000 ~了乎?

[root@www ~]# find /bin /sbin -perm +6000

上述范例中比较有趣的就属 -perm 这个选项啦!他的重点在找出特殊权限的档案啰! 我们知道 SUID 与 SGID 都可以设定在二进位程式上,假设我想要找出来 /bin, /sbin 这两个目录下, 只要具有 SUID 或 SGID 就列出来该档案,你可以这样做:

因为 SUID 是 4 分,SGID 2 分,总共为 6 分,因此可用 +6000 来处理这个权限! 至于 find 后面可以接多个目录来进行搜寻!另外, find 本来就会搜寻次目录,这个特色也要特别注意喔! 最后,我们再来看一下 find 还有什么特殊功能吧!

find 的特殊功能就是能够进行额外的动作(action)。我们将范例八的例子以图解来说明如下:


图5.2.2、find 相关的额外动作
该范例中特殊的地方有 {} 以及 ; 还有 -exec 这个关键字,这些东西的意义为:

  • {} 代表的是‘由 find 找到的内容’,如上图所示,find 的结果会被放置到 {} 位置中;
  • -exec 一直到 ; 是关键字,代表 find 额外动作的开始 (-exec) 到结束 (;) ,在这中间的就是 find 指令内的额外动作。 在本例中就是‘ ls -l {} ’啰!
  • 因为‘ ; ’在 bash 环境下是有特殊意义的,因此利用反斜线来跳脱。

透过图 5.2.2 你应该就比较容易了解 -exec 到 ; 之间的意义了吧!

如果你要找的档案是具有特殊属性的,例如 SUID 、档案拥有者、档案大小等等, 那么利用 locate 是没有办法达成你的搜寻的!此时 find 就显的很重要啦! 另外,find 还可以利用万用字元来找寻档名呢!举例来说,你想要找出 /etc 底下档名包含 httpd 的档案, 那么你就可以这样做:

[root@www ~]# find /etc -name '*httpd*'

不但可以指定搜寻的目录(连同次目录),并且可以利用额外的选项与参数来找到最正确的档名!真是好好用! 不过由于 find 在寻找资料的时后相当的操硬碟!所以没事情不要使用 find 啦!有更棒的指令可以取代呦!那就是上面提到的 whereis 与 locate 啰!


参数代换: xargs

xargs 是在做什么的呢?就以字面上的意义来看, x 是加减乘除的乘号,args 则是 arguments (参数) 的意思,所以说,这个玩意儿就是在产生某个指令的参数的意思! xargs 可以读入 stdin 的资料,并且以空白字元或断行字元作为分辨,将 stdin 的资料分隔成为 arguments 。 因为是以空白字元作为分隔,所以,如果有一些档名或者是其他意义的名词内含有空白字元的时候, xargs 可能就会误判了~他的用法其实也还满简单的!就来看一看先!

[root@www ~]# xargs [-0epn] command
选项与参数:
-0  :如果输入的 stdin 含有特殊字元,例如 `, , 空白键等等字元时,这个 -0 参数可以将他还原成一般字元。这个参数可以用于特殊状态喔!
-e  :这个是 EOF (end of file) 的意思。后面可以接一个字串,当 xargs 分析到这个字串时,就会停止继续工作!
-p  :在执行每个指令的 argument 时,都会询问使用者的意思;
-n  :后面接次数,每次 command 指令执行时,要使用几个参数的意思。看范例三。
当 xargs 后面没有接任何的指令时,预设是以 echo 来进行输出喔!

范例一:将 /etc/passwd 内的第一栏取出,仅取三行,使用 finger 这个指令将每个帐号内容秀出来
[root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs finger
Login: root                             Name: root
Directory: /root                        Shell: /bin/bash
Never logged in.
No mail.
No Plan.
......底下省略.....
# 由 finger account 可以取得该帐号的相关说明内容,例如上面的输出就是 finger root
# 后的结果。在这个例子当中,我们利用 cut 取出帐号名称,用 head 取出三个帐号,
# 最后则是由 xargs 将三个帐号的名称变成 finger 后面需要的参数!

范例二:同上,但是每次执行 finger 时,都要询问使用者是否动作?

[root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs -p finger
finger root bin daemon ?...y
.....(底下省略)....
# 呵呵!这个 -p 的选项可以让使用者的使用过程中,被询问到每个指令是否执行!

范例三:将所有的 /etc/passwd 内的帐号都以 finger 查阅,但一次仅查阅五个帐号
[root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -n 5 finger
finger root bin daemon adm lp ?...y

.....(中间省略)....
finger uucp operator games gopher ftp ?...y
.....(底下省略)....
# 在这里鸟哥使用了 -p 这个参数来让您对于 -n 更有概念。一般来说,某些指令后面
# 可以接的 arguments 是有限制的,不能无限制的累加,此时,我们可以利用 -n
# 来帮助我们将参数分成数个部分,每个部分分别再以指令来执行!这样就 OK 啦!^_^

范例四:同上,但是当分析到 lp 就结束这串指令?
[root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -e'lp' finger
finger root bin daemon adm ?...
# 仔细与上面的案例做比较。也同时注意,那个 -e'lp' 是连在一起的,中间没有空白键。
# 上个例子当中,第五个参数是 lp 啊,那么我们下达 -e'lp' 后,则分析到 lp
# 这个字串时,后面的其他 stdin 的内容就会被 xargs 舍弃掉了!

其实,在 man xargs 里面就有三四个小范例,您可以自行参考一下内容。 此外, xargs 真的是很好用的一个玩意儿!您真的需要好好的参详参详!会使用 xargs 的原因是, 很多指令其实并不支援管线命令,因此我们可以透过 xargs 来提供该指令引用 standard input 之用!举例来说,我们使用如下的范例来说明:

范例五:找出 /sbin 底下具有特殊权限的档名,并使用 ls -l 列出详细属性
[root@www ~]# find /sbin -perm +7000 | ls -l
# 结果竟然仅有列出 root 所在目录下的档案!这不是我们要的!
# 因为 ll (ls) 并不是管线命令的原因啊!

[root@www ~]# find /sbin -perm +7000 | xargs ls -l
-rwsr-xr-x 1 root root 70420 May 25  2008 /sbin/mount.nfs
-rwsr-xr-x 1 root root 70424 May 25  2008 /sbin/mount.nfs4
-rwxr-sr-x 1 root root  5920 Jun 15  2008 /sbin/netreport
....(底下省略)....
减号 – 的用途

管线命令在 bash 的连续的处理程序中是相当重要的!另外,在 log file 的分析当中也是相当重要的一环, 所以请特别留意!另外,在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的 stdin , 某些指令需要用到档案名称 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 “-” 来替代, 举例来说:

[root@www ~]# tar -cvf - /home | tar -xvf -

上面这个例子是说:‘我将 /home 里面的档案给他打包,但打包的资料不是纪录到档案,而是传送到 stdout; 经过管线后,将 tar -cvf – /home 传送给后面的 tar -xvf – ’。后面的这个 – 则是取用前一个指令的 stdout, 因此,我们就不需要使用 file 了!这是很常见的例子喔!注意注意!


Linux系统中的find命令和xargs命令详解
参考链接:

  • xargs command is designed to construct argument lists and invoke other utility. xargs reads items from the standard input or pipes, delimited by blanks or newlines, and executes the command one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.

    xargs is more safer and easy to use

    xargs functionality can be achived using the backquote feature of shell. But, it offers more options. It can deal with blanks or special characters in file names easily. It is often used with find, grep and other commands.

    xargs examples

    For example following example will print 1 2 3 4 using xargs (echo command is default)
    $ echo 1 2 3 4 | xargs echo
    OR
    $ echo 1 2 3 4 | xargs
    You can force xargs to use at most max-args arguments per command line. For example following will use first two argument per command:
    $ echo 1 2 3 4 | xargs -n 2
    Find all .bak files in or below the current directory and delete them.
    $ find . -name "*.bak" -type f -print | xargs /bin/rm -f

    {} as the argument list marker

    {} is the default argument list marker. You need to use {} this with various command which take more than two arguments at a time. For example mv command need to know the file name. The following will find all .bak files in or below the current directory and move them to ~/.old.files directory:
    $ find . -name "*.bak" -print0 | xargs -0 -I {} mv {} ~/old.files
    You can rename {} to something else. In the following example {} is renamed as file. This is more readable as compare to previous example:
    $ find . -name "*.bak" -print0 | xargs -0 -I file mv file ~/old.files
    Where,

    1. -0 If there are blank spaces or characters (including newlines) many commands will not work. This option take cares of file names with blank space.
    2. -I Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character.

    Dealing file names with blank spaces and newline

    The following will work incorrectly if there are any filenames containing newlines or spaces (it will find out all .mp3 file located in current directory and play them using mplayer):
    $ find . -iname "*.mp3" -print | xargs mplayer
    To get rid of this problem use -0 option:
    $ find . -iname "*.mp3" -print0 | xargs -0 -I mp3file mplayer mp3file
    To find out all *.c file located in 100s of subdirectories and move them to another directory called ~/old.src, use:
    $ find /path/to/dir -iname "*.c" -print0 | xargs -0 -I file mv file ~/old.src

    Avoiding errors and resource hungry problems with xargs and find combo

    To copy all media files to another location called /bakup/iscsi, you can use cp as follows:
    $ cp -r -v -p /share/media/mp3/ /backup/iscsi/mp3
    However, cp command may fail if an error occurs such as if the number of files is too large for the cp command to handle. xargs in combination with find can handle such operation nicely. xargs is more resource efficient and will not halt with an error:

    $ find /share/media/mp3/ -type f -name "*.mp3" -print0 | xargs -0 -r -I file cp -v -p file --target-directory=/bakup/iscsi/mp3

    Please note that all of the above commands are tested with GNU/xargs version. BSD and UNIX xargs command may not have options such as -r. Please refer to your local xargs man page for further info:

    man xargs

  • —————–
  • xargs is a just like “awk” ,”find” & “grep” commands processes the standard input on all unix flavoured operating sysems.
    Basically “xargs” is used to remove or do some operation on long list of file names which were produced by “find” & “grep” commands.Usually many UNIX operating system doesn’t accept such a long list of argument.UNIX xargs command divide that list into sub-list with acceptable length and made it work.For example I’d like to find out all *.sh file located in 100s of sub-directories and move them to another directory called ~/back.scripts. How do I use command line args with xargs to achieve the same?as per man page “xargs” is used to execute a command, passing constructed argument list(s). The arguments are typically a long list of filenames (generated by ls or find etc) that are passed to xargs via a pipe.

    Some features:

    • xargs can execute the command supplying some initial arguments directly, and reading the remaining arguments from standard input (or piped input).
    • xargs passes arguments to command in several bundles, this allows command to process more arguments than it could normally handle at once.
    • Arguments in the standard input must be separated by unquoted blank characters, or unescaped blank characters or newline characters.
    • Characters can be quoted by enclosing them in “double-quotes” (non-double-quote and non-newline chars only).
    • Characters can be quoted by enclosing them in ‘apostrophes’ (non-apostrophe and non-newline chars only).
    • Any unquoted character can be escaped by preceding it with a backslash.
    e.g. file1 file2 “file three” ‘file four’ file five
    If command is omitted then the equivalent of /bin/echo is used.

     Exit Status

    This command returns the following exit values:
    Item Description
    0 All invocations of the Command parameter returned exit status 0.
    1-125 A command line meeting the specified requirements could not be assembled, one or more of the invocations of the Command parameter returned a non-zero exit status, or some other error occurred.
    126 Command was found but could not be invoked.
    127 Command could not be found.

    Examples

    Find all the .mp3 files in the music folder and pass to the ls command, -print0 is required if any filenames contain whitespace.:

       find ./music -name “*.mp3” -print0 | xargs -0 ls

    Find all files in the work folder, pass to grep and search for profit:

       find ./work -print | xargs grep “profit”

    {} as the argument list marker

    {} is the default argument list marker. You need to use {} this with various command which take more than two arguments at a time. For example mv command need to know the file name. The following will find all .bak files in or below the current directory and move them to ~/.old.files directory:
    $ find . -name “*.sh” -print0 | xargs -0 -I {} mv {} ~/back.scripts

    You can rename {} to something else. In the following example {} is renamed as file. This is more readable as compare to previous example:

    $ find . -name “*.sh” -print0 | xargs -0 -I file mv file ~/back.scripts

    Where,
    -0 If there are blank spaces or characters (including newlines) many commands will not work. This option take cares of file names with blank space.(用于处理文件名中含有空格或空行等空白字符的情况)
    -I Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character.

    10 Popular  “XARGS” Command Examples:

    1) With& Without “xargs” observation:

     in this example of xargs command we will see how output changes with use of xargs command in unix or Linux. Here is the output of find command without xargs first and than with xargs, you can clearly see that multiline output is converted into single line:

    um@server#find . -name “*sh*”
    ./.bash_history
    ./.bash_profile
    ./.bash_profile.cf-before-edit
    ./.cshrc
    ./.cshrc.cf-before-edit
    ./.sh_history
    ./.ssh
    ./.ssh2
    ./scripts/aix_sysinfo.ksh
    ./scripts/chperm_messages.sh
    ./scripts/linux_sysinfo.ksh
    ./scripts/solaris_sysinfo_v1.1.ksh
    ./testlocked.kshum@server# find . -name “*bash*” | xargs
    ./.bash_history ./.bash_profile ./.bash_profile.cf-before-edit ./.cshrc ./.cshrc.cf-before-edit ./.sh_history ./.ssh ./.ssh2 ./scripts/aix_sysinfo.ksh ./scripts/chperm_messages.sh ./scripts/linux_sysinfo.ksh ./scripts/solaris_sysinfo_v1.1.ksh ./testlocked.ksh

    2) Xargs with grep:

    When you use “xargs” in conjusction with find and grep , the grep will look for the specifig word in  each file in the from the stanadard input.

    #find . -name “*.sh” | xargs grep “ksh”

    In the above exanmple first find all .sh  files from current directory or below and than on each .sh file look for word “ksh”.

    3) Covert muti line output into single line

    best example of xargs is  converting output of one command into one line. For example you can run any command and then combine xargs to convert output into single line. here is an example xargs in unix which does that.

    um@server#ls -1 *.sh
    linux_sysinfo.sh
    aix_sysinfo.sh
    audit_script.sh
    chperm_messages.shum@system#ls -1 *.sh | xargs
    linux_sysinfo.sh aix_sysinfo.sh audit_script.sh chperm_messages.sh

    4) To Delete temporary files using xargs & find:

    Another common example of xargs command in unix is removing temporary files from system.

    #find /tmp -name “*.tmp” | xargs rm

    This will remove all .tmp file from /tmp or below directory. xargs in unix is very fast as compared to deleting single file at a time which can also be done by using find command alone

    5)  xargs -0 to handle space in file name

    Above example of xargs command in unix will not work as expected if any of file name contains space or new line on it. To avoid this problem we use find -print0 to produce null separated file name and xargs-0 to handle null separated items. Here is an example of xargs command in unix which can handle file name with spaces and newline:

    #find /tmp -name “*.tmp” -print0 | xargs -0 rm

    6) Counting number of lines/words/characters in each file using xargs & find:

    “find”in conjuction with “xargs” and “wc”  we can count number of lines/words/characters in each file under a perticaular directory.

    um@server#ls -1 *.sh | xargs wc -l
    112 linux_sysinfo.sh
    85  aix_sysinfo.sh
    35  audit_script.sh
    18  chperm_messages.sh
    250 total

    Note: you can use ‘-c’ & ‘-w’ with wc to obtain number of characters and words repectively.

    7) xargs and cut command in Unix:

     Though most of xargs examples in unix will be along with find and grep command but xargs is not just limited to this two it can also be used with any command which generated long list of input for example we can use xargs with cut command in unix. In below example of unix xargs we will xargs example with cut command. for using cut command let’s first create a .csv file with some data e.g.

    um@server# cat fruits.txt
    Orange,Greenorange
    Mango,Redmango
    Banana,PinkbananaNow we will display name of actual fruit from first column using xargs command in one line:um@server:/etc cut -d, -f1 smartphones.csv | sort | xargs
    Orange Mango Banana

    8)To insert file names into the middle of command lines, type:(批量重命名,而且考虑到了文件名中的空白符等特殊字符

    um@server#ls | xargs  -t  -I  {} mv {} {}.oldThis command sequence renames all files in the current directory by adding .old to the end of each name. The -I flag tells the xargs command to insert each line of the ls directory listing where {} (braces) appear. If the current directory contains the files chap1, chap2, and chap3, this constructs the following commands:#mv chap1 chap1.old
    #mv chap2 chap2.old
    #mv chap3 chap3.old

    9) To run a command on files that you select individually, type:

    um@server# ls | xargs  -p  -n  1 ar r lib.aThis command sequence allows you to select files to add to the lib.a library. The -p flag tells the xargs command to display each ar command it constructs and to ask if you want to run it. Type y to run the command. Press the any other key if you do not want to run the command.Something similar to the following displays:ar r lib.a chap1 ?…
    ar r lib.a chap2 ?…
    ar r lib.a chap3 ?…

    10) To construct a command that contains a specific number of arguments and to insert those arguments into the middle of a command line, type:

    um@server# ls | xargs -n6 | xargs -I{} echo {} – some files in the directoryIf the current directory contains files chap1 through chap10, the output constructed will be the following:
    chap1 chap2 chap3 chap4 chap5 chap6 – some files in the directory
    chap7 chap8 chap9 chap10 – some file in the directory

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/156.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注