当前位置: 首页 > 编程日记 > 正文

Linux Find 命令精通指南

作者:Sheryl Calish

Linux find 命令是所有 Linux 命令中最有用的一个,同时也是最混乱的一个。它很难,因为它的语法与其他 Linux 命令的标准语法不同。但是,它很强大,因为它允许您按文件名、文件类型、用户甚至是时间戳查找文件。使用 find 命令,您不但可以找到具这些属性任意组合的文件,还可以对它找到的文件执行操作。

本文的目的是,通过概述 find 命令的用途和潜能,简化该命令的学习和使用。同时,它将针对 find 命令的某些最强大但最混乱的方面提供一个基本的指南和参考。

[注意:本文使用的 find 版本是 GNU 版本,因此,某些细节可能与其他版本的 find 有所不同。]

基本格式

开始之前,我们先来看一下 find 命令的基本结构:

find  start_directory  test  options  criteria_to_match
action_to_perform_on_results

在以下命令中,find 将开始在当前目录(用“.”表示)中查找任何扩展名为“java”的文件:

find . -name "*.java"  

下面是该命令所找到的命令的缩略清单:

find . -name "*.java"
./REGEXPvalidate/src/oracle/otnsamples/plsql/ConnectionManager.java
./REGEXPvalidate/src/oracle/otnsamples/plsql/DBManager.java
..

[注意:如果您从本文剪切并粘贴来运行该 find 命令,您可能需要使用自己的键盘替换双引号 (“”) 才能得出正确的结果。]

以下命令将执行相同的操作。在这两种情况下,您都需要对通配符进行转义以确保它传递到 find 命令并且不由 shell 解释。因此,请将您的搜索字符串放到引号里,或者在它前面加上反斜线:

find . -name /*.java

尽管 find 的所有参数均为可选,但是如果您未指定从哪里开始搜索,搜索默认将在当前目录中开始。如果您不指定要匹配的测试连接、选项或值,您的结果将不完整或者无区别。
 
运行以下三个 find 命令将得出同样的结果 — 当前目录和所有子目录中的所有文件(包括隐藏文件)的完整清单:

find 
find .
find . -print

这类似于运行一个带 -la 选项的 ls 命令。如果您希望上述命令的输出包含完整的路径名(或许是为了备份),您将需要指定起始目录的完整路径:

find /home/bluher -name /*.java
/home/bluher/plsql/REGEXPvalidate/src/oracle/otnsamples/plsql/ConnectionManager.java
/home/bluher/plsql/REGEXPvalidate/src/oracle/otnsamples/plsql/DBManager.java/
...

您还可以在搜索字符串中指定多个起始目录。如果以具有相应权限的用户身份运行,以下命令将下到 /usr、/home /tmp 目录查找所有 jar 文件:

find /usr /home /tmp -name "*.jar"

但是,如果您没有相应的权限,您在开始浏览许多系统目录时将生成错误消息。以下是一个示例:

find: /tmp/orbit-root: Permission denied

您可以通过附加您的搜索字符串来避免混乱的输出,如下所示:

find /usr /home /tmp -name "*.jar" 2>/dev/null

这会将所有错误消息发送到空文件,因此提供清理器输出。

默认情况下,find 是区分大小写的。对于不区分大小写的 find,将 -iname 测试替换为 -name 测试。

find downloads -iname "*.gif"
downloads/.xvpics/Calendar05_enlarged.gif
downloads/lcmgcfexsmall.GIF

除文件名外,您还可以按类型搜索文件。例如,您可以使用以下命令查找一个目录中的所有子目录:

find . -type d         

您可以使用以下命令查找您的/usr 目录中的所有符号链接:

find /usr -type l

这可能会列出 3,000 多个链接。以下的任何一个命令使用根权限运行都将列出 /usr 目录中的链接以及它所指向的文件:

# find /usr/bin -type l  -name "z*" -exec ls -l {} /;
lrwxrwxrwx 1 root root 8 Dec 12 23:17 /usr/bin/zsh -> /bin/zsh
lrwxrwxrwx 1 root root 5 Dec 12 23:17 /usr/bin/zless -> zmore
lrwxrwxrwx 1 root root 9 Dec 12 23:17 /usr/bin/zcat -> /bin/zcat
find /usr/bin -type l  -name "z*" -ls

但是,第二个更短的命令将列出更多的文件,以及目录和 inode 信息:在本文后面的部分中,我们将讨论 -exec 和 -ls 操作的用法。

其他 find 可以找到的文件类型包括:

• b — 块(缓存)特殊
• c — 字符(未缓存)特殊
• p — 命名管道 (FIFO)
• s — 套接字

使用根作为 find 命令的起点会极大地降低系统的速度。如果您必须运行这样一个命令,您可以在非高峰时段或晚上运行它。您可以使用以下语法将输出重定向到一个文件:

find  /  -print > masterfilelist.out

如果您错误地输入一个 find 命令,生成大量不必要的输出,只需按 CTRL-C 中断该命令,这将停止最近执行的命令。

在具多个文件系统的企业网络上,限制 find 查找的文件也是一个特别好用的方法。尽可能多地使用选项和测试以减少系统上的负载。用于此目的的两个最有用的选项是 -xdev 和 -mount。它们通过阻止 find 下到其他文件系统(如 MS-DOS、CD-ROM 或 AFS)上的目录中缩短了搜索范围。这将搜索限制为同一类型的文件系统作为起始目录。

如果运行 mount 命令,双引导系统上的用户可以使用这些选项。假设涉及 Windows 分区,您可以使用类似以下的命令安装它:

mount -t vfat /dev/sda1 /mnt/msdos

您使用的实际命令取决于您的系统设置。您可以通过运行 df 或执行以下命令验证该分区已安装:

find /mnt/msdos -name "*.txt" 2> /dev/null

您应该看到 MS Windows 分区上列出了很多的文件。现在,运行以下带 -mount 或 -xdev 选项的命令:

find / -name "*.txt" -mount 2> /dev/null

或者

find / -name "*.txt" -xdev 2> /dev/null

还可以使用 -fstype 测试明确告知 find 在哪个文件系统中查找,如以下示例中所示:

find / -name "*.txt" -fstype vfat 2> /dev/null

查找时间

find 命令有几个用于根据您系统的时间戳搜索文件的选项。这些时间戳包括

mtime 文件内容上次修改时间
atime — 文件被读取或访问的时间
ctime — 文件状态变化时间

mtime 和 atime 的含义都是很容易理解的,而 ctime 则需要更多的解释。由于 inode 维护着每个文件上的元数据,因此,如果与文件有关的元数据发生变化,则 inode 数据也将变化。这可能是由一系列操作引起的,包括创建到文件的符号链接、更改文件权限或移动了文件等。由于在这些情况下,文件内容不会被读取或修改,因此 mtime 和 atime 不会改变,但 ctime 将发生变化。

这些时间选项都需要与一个值 n 结合使用,指定为 -n、n+n

• -n 返回项小于 n
• +n
返回项大于 n
• n
返回项正好与 n 相等

下面,我们来看几个例子,以便于理解。以下命令将查找在最近 1 小时内修改的所有文件:

find . -mtime -1
./plsql/FORALLSample
./plsql/RegExpDNASample
/plsql/RegExpSample

用 1 取代 -1 运行同一命令将查找恰好在 1 小时以前修改的所有文件:

find . -mtime 1

上述命令不会生成任何结果,因为它要求完全吻合。以下命令查找 1 个多小时以前修改的所有文件:

find . -mtime +1

默认情况下,-mtime、-atime 和 -ctime 指的是最近 24 小时。但是,如果它们前面加上了开始时间选项,则 24 小时的周期将从当日的开始时间算起。您还可以使用 mmin、amin 和 cmin 查找在不到 1 小时的时间内变化了的时间戳。

如果您在登录到您的帐户后立即运行以下命令,您将找到在不到 1 分钟以前读取的所有文件:

find . -amin -1
./.bashrc
/.bash_history
./.xauthj5FCx1

应该注意的是,使用 find 命令查找文件本身将更改该文件的访问时间作为其元数据的一部分。

您还可以使用 -newer、-anewer 和 –cnewer 选项查找已修改或访问过的文件与特定的文件比较。这类似于 -mtime、-atime 和 –ctime。
 
• -newer 指内容最近被修改的文件
• -anewer 指最近被读取过的文件
• -cnewer 指状态最近发生变化的文件

要查找您的主目录中自上一个 tar 文件以来以某种方式编辑过的所有文件,使用以下命令:

find . -newer backup.tar.gz

按大小查找文件

-size 选项查找满足指定的大小条件的文件。要查找所有大于 5MB 的用户文件,使用

find / -size +5000000c 2> /dev/null
/var/log/lastlog
/var/log/cups/access_log.4
/var/spool/mail/bluher

结尾的“c”以字节为单位报告我们的结果。默认情况下,find 以 512 字节块的数量报告大小。如果我们将“c”替换为“k”,我们还会看到以千字节的数量报告的结果,如果使用“w”,则会看到以两字节字的数量报告的结果。

-size 选项经常用于搜索所有零字节文件并将它们移至 /tmp/zerobyte 文件夹。以下命令恰好可以完成这一任务:

find test -type f -size 0 -exec mv {} /tmp/zerobyte /;

-exec 操作允许 find 在它遇到的文件上执行任何 shell 命令。在本文的后面部分,您将看到其用法的更多示例。大括号允许移动每个空文件。

选项 -empty 还可用于查找空文件:

find test -empty        
test/foo
test/test

按权限和所有者查找

要监视您的系统安全离不开 find 命令。您可以使用符号或八进制表示法查找面向广大用户开放的文件,如下所示:

find . -type f -perm a=rwx -exec ls -l {} /;

或者

find . -type f -perm 777 -exec ls -l {} /;
-rwxrwxrwx 1 bluher users 0 May 24 14:14 ./test.txt

在这一部分中,在上面和下面的命令中,我们使用了 -exec ls -l 操作,因此,您可以看到返回的文件的实际权限。以下命令将查找可由“other”和组写入的文件:

find plsql -type f -perm -ug=rw -exec ls -l {} /; 2>/dev/null

或者

find plsql -type f -perm -220 -exec ls -l {} /; 2>/dev/null 
-rw-rw-rw- 1 bluher users 4303 Jun  7  2004 plsql/FORALLSample/doc/otn_new.css
-rw-rw-rw- 1 bluher users 10286 Jan 12  2005 plsql/FORALLSample/doc/readme.html
-rw-rw-rw- 1 bluher users 22647 Jan 12  2005 plsql/FORALLSample/src/config.sql
..

下一个命令将查找由用户、组或二者共同写入的文件:

find plsql -type f -perm /ug=rw -exec ls -l {} /; 2>/dev/null, or,
find plsql -type f -perm /220 -exec ls -l {} /; 2>/dev/null 
-rw-r--r-- 1 bluher users 21473 May  3 16:02 plsql/regexpvalidate.zip
-rw-rw-rw- 1 bluher users 4303 Jun  7  2004 plsql/FORALLSample/doc/otn_new.css
-rw-rw-rw- 1 bluher users 10286 Jan 12  2005 plsql/FORALLSample/doc/readme.html
-rw-rw-rw- 1 bluher users 22647 Jan 12  2005 plsql/FORALLSample/src/config.sql

您可能会看到以下命令在 Web 和较早的手册中引用过:

find . -perm +220 -exec ls -l {} /; 2> /dev/null

+ 符号的作用与 / 符号相同,但是现在新版 GNU findutils 中不支持使用该符号。

要查找您的系统上所有人都可以写入的所有文件,使用以下命令:

find / -wholename '/proc' -prune  -o  -type f -perm -0002 -exec ls -l {} /;
-rw-rw-rw- 1 bluher users 4303 Jun  7  2004/home/bluher/plsql/FORALLSample/doc/otn_new.css
-rw-rw-rw- 1 bluher users 10286 Jan 12  2005 /home/bluher/plsql/FORALLSample/doc/readme.html
...

第 4 个权限将在稍后进行讨论,但最后一个字段中的“2”是文件权限中的“other”字段,也称为写入位。我们在权限模式 0002 前面使用了破折号,以指明我们希望看到为 other 设置了写权限的文件,无论其他权限设置为什么。

上述命令还引入了三个新概念。针对文件模式“/proc”使用 -wholename 测试,如果该模式已找到,-prune 可防止 find 下到该目录中。布尔类型“-o”使 find 可以针对其他目录处理该命令的其余部分。由于每个表达式之间有一个假设的隐式 and 运算符 (-a),因此,如果左侧的表达式计算结果为 false,and 之后的表达式将不进行计算;因此需要 -o 运算符。Find 还支持布尔类型 -not、!,就像使用括号强行优先一样。

系统管理员经常使用 find 通过用户或组的名称或 ID 搜索特定用户或组的常规文件:

[root] $  find / -type f -user bluher -exec ls -ls {} /;

下面是这样一个命令的高度精简的输出示例:

4 -rw-r--r-- 1 bluher users 48 May  1 03:09 /home/bluher/public_html/.directory
4 -rw-r--r-- 1 bluher users 925 May  1 03:09 /home/bluher/.profile

您还可以使用 find 按组查找文件:

[root] $ find / -type f -group users
find / -type d -gid 100

该命令将列出由 ID 为 100 的组拥有的目录。要找到相应的 uid 或 gid,您可以针对 /etc/passwd 或 /etc/group 文件运行 more 或 cat 命令。

除了查找特定已知用户和组的文件外,您还会发现它对于查找没有这些信息的文件也很有用。下一个命令将识别未列在 /etc/passwd 或 /etc/group 文件中的文件:

find / -nouser -o -nogroup

上述命令可能不会在您的系统上生成实际的结果。但是,它可用于识别或许在经常移动后没有用户或组的文件。

好了,现在我们可以解决本部分开始时提到的格外重要的权限了。

SGID 和 SUID 是特殊访问权限标志,可以分配给基于 UNIX 的操作系统上的文件和目录。设置它们是为了允许访问计算机系统的普通用户使用临时提升的权限执行二进制可执行文件。

find /  /( -perm -2000 -o -perm -4000 /) -ls
167901   12 -rwsr-xr-x   1 root     root         9340 Jun 16  2006 /usr/bin/rsh
167334   12 -rwxr-sr-x   1 root     tty         10532 May  4  2007 /usr/bin/wall

在上述命令中,您可以看到转义括号的使用。您还可以看到权限的不同。第一个文件设置了 SGID 权限,第二个文件设置了 SUID 权限。上述命令中的最后的操作与带 -exec ls -dils 操作的 find 效果类似。

控制 find

与 Linux 中的许多命令不同,find 不需要 -r 或 -R 选项即可下到子目录中。它默认情况下就这样操作。但是,有时您可能希望限制这一行为。因此,选项 -depth、-maxdepth 和 -mindepth 以及操作 -prune 就派上用场了。

我们已经看到了 -prune 是多么有用,下面让我们来看看 -depth、-maxdepth 和 -mindepth 选项。

-maxdepth 和 -mindepth 选项允许您指定您希望 find 搜索深入到目录树的哪一级别。如果您希望 find 只在目录的一个级别中查找,您可以使用 maxdepth 选项。

通过运行以下命令在目录树的前三个级别中查找日志文件,您可以看到 -maxdepth 的效果。使用该选项较之不使用该选项所生成的输出要少得多。

find / -maxdepth 3 -name "*log"

您还可以让 find 在至少下至目录树三个级别的目录中查找:

find / -mindepth 3 -name "*log"

-depth 选项确保先在一个目录中进行查找,然后才在其子目录中进行查找。以下命令提供了一个示例:

find -name "*test*" -depth
./test/test
./test
./localbin/test
./localbin/test_shell_var
./localbin/test.txt
./test2/test/test
./test2/test
./test2

find 世界

我们已经看过了 find 命令的一些更加有用以及有点难懂的功能,但是 find 还可以执行更多的任务。例如,有多个选项可以使 find 与较低的 UNIX 版本和其他操作系统相兼容并允许您执行打印输出到多个文件等操作。阅读本文后,您现在已经有了理解 find 参考指南的背景,我鼓励您深入研究这一强大、有用的工具。

相关文章:

【安全运维】 linux 系统账户,网络,简易安全加固方案(第一部分),经测试可行...

前言讲到linux系统账户的管理以及安全,就必须涉及 /etc/passwd /etc/shadow 这2个文件这里以截图中文字说明的方式,来分析这2个文件的内容,并且给出一些实用的安全加固方案注意,本文会持续更新,后续加入的内容都以直…

不用深度学习,怎么提取图像特征?

来源 | 小白学视觉头图 | 下载于ICphoto图像分类是数据科学中最热门的领域之一,在本文中,我们将分享一些将图像转换为特征向量的技术,可以在每个分类模型中使用。VATboxVATbox,作为n一个我们所暗示的,涉及增值税问题&a…

课程第五天内容《基础交换 五》

2019独角兽企业重金招聘Python工程师标准>>> 以太网/LAN(local area network )的相关概念: 问题: 信号传输距离有限; 解决方案: 中继器 - 放大电信号,延长信息的传输距离&#xff1…

C#综合揭秘——Entity Framework 并发处理详解

引言 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的错误的一种机制。从 ADO.NET 到 LINQ to SQL 再到如今的 ADO.NET Entity Framework,.NET 都为并发控制提供好良好的支持方案。 并发处理方式一般分为乐观必并发与悲观必并发两种&#xff0…

@2021高考生,用 Python 分析专业“钱景”

来源 | 关于数据分析于可视化头图 | 下载于ICphoto2021年的高考在昨日拉开帷幕,十年的寒窗苦读,终于到了最后见分晓的时候了。在这么一场关键的考试当中,除了考试前努力奋斗,考场上认真答题,考后的志愿填报也是极其的重…

Linux下C语言的fgets与fputs

使用的是 CentOS gcc编译下面程序 显示warning: the gets function is dangerous and should not be used.问题出在程序中使用了 gets Linux 下gcc编译器不支持这个函数,解决办法是使用 fgets fgets()函数的基本用法为: fgets(char * s,int size,FILE * …

linux发行版的用户交互

1 cli,即command line interface 纯命令行的交互方式,该命令行界面是由shell提供的。 linux内核本身也自带了一个console,即linux console,它是基于frame buffer的。 cli的界面都是基于ncurses库开发的。 2 GUI,graphi…

C#中在应用程序和DLL使用消息

在C#中采用的是事件驱动方式,但在我们使用的过程中,有时候通过调用系统原有的消息,处理起来会比较简单一些,特别是在处理与DLL文件的交互时,的确是非常的方便。 在C#中使用自定义消息 在C#中使用自定义消息非常简单&…

倪光南院士:openEuler与全球开发者共同推动计算产业发展

今日,以“创造最好的OS,成就更好的我们”为主题的 openEuler Developer Day 2021在北京成功举行。本次大会由openEuler社区发起,产业组织专家、学者、企业领袖和开发者们围绕多样性计算、云原生全栈、全场景协同等技术方向共同探讨和创新。大…

jhello框架-ajax

2019独角兽企业重金招聘Python工程师标准>>> 现在的web开发没有ajax都没法活,所以在jhello中实现了一个简单的ajax交互,使用json作为载体。 在上篇《交互》中讲到一种交互的方式是把数据放入Model中,通过ModelAndView类返回到视图…

发微信模版消息换行用\n

发微信模版消息换行用\n发微信模版消息换行用\n发微信模版消息换行用\n发微信模版消息换行用\n发微信模版消息换行用\n转载于:https://blog.51cto.com/xuqin/1974131

二次元会让人脸识别失效吗?

来源 | PyTorch 开发者社区责编 | 寇雪芹头图 | 下载于ICphoto人脸识别也遇到坑了,识别得了三次元,却对二次元无效。迪士尼的技术团队,正在开发这一算法,以帮助动画制作者进行后期搜索。团队利用 PyTorch,效率得到很大…

基于第四层交换技术的负载均衡

摘 要 本文介绍了第四层交换技术的概念,技术原理以及如何使用第四层交换技术实现远程教育系统中的应用服务器负载均衡。 作者: 凌仲权,现就读于西安电子科技大学,2001级硕士研究生。主要的科研方向为计算机网络技术研究以及远程教…

開始Unity3D的学习之旅

前言:这个系列的文章纯属对自己学习的整理,非高手之作。但确实的记载了我作为一个没接触过3D游戏编程的大学生的心路历程。争取每周整理一次吧。之所以会開始学Unity3D,最基本的原因是由于在快放暑假的时候,我找了一家做iPhone游戏…

linux 定时任务crond

1.定时任务crond 1.1 crond是什么 crond是linux系统中用来定期执行命令或指定程序任务的一种服务或软件。特殊需求:(秒级别)crond服务就无法搞定了,一般工作中写脚本守护进程执行。 为什么要使用crond定时任务: linux系…

用C#去除代码的SourceSafe管理

经常看一些的程序,有些一个解决方案带有多个项目,由于代码比较多,多人开发,所以好多vs.net下的工程是用source safe进行版本控制的。而用source safe进行版本控制需要局域网路径共享,因此好多项目换一台机器打开会出现…

用jarsigner对android apk进行签名

以前对apk重新打包签名都是用的apktool里面的Auto-sign 工具,后来发现有时候利用该工具对一些apk签名会失败,所以后来就使用 jarsigner这个工具,现记录一下这个工具的使用方法1 首先要生成一个自己的keyD:\>keytool -genkey -alias myKey…

利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上的疏散耦合,而非…

C#操作消息队列

public class QueueManage { /// /// 发送对象到队列中 /// /// 队列名称,因为队列名称在一个应用中应该不改变的,所以大家最好写在配置文件中 /// 要发出去的对象 public static void SendQueue(string QueuePath,MyBase.SmsQueue sq) { Syste…

2021《程序员》数字科技企业研发实力榜TOP50

互联网的盛行带来了众多数字科技企业的崛起,但如何客观地衡量每家企业的技术实力?研发投入、研发人才的数量和人才密度是关键指标。2021年5月,《程序员》根据相关企业披露的财报数据及市场调研数据,整理发布“2021数字科技企业研发实力榜TOP5…

eclipse中java项目转换为web项目

2019独角兽企业重金招聘Python工程师标准>>> 经常在eclipse中导入web项目时,出现转不了项目类型的问题,导入后就是一个java项目,有过很多次经历,今天也有同事遇到类似问题,就把这个解决方法记下来吧&#x…

MySQL · 引擎介绍 · Sphinx源码剖析(三)

在本节中我会介绍Sphinx在构建索引之前做的一些事情,主要是从mysql拉取数据保存,然后分词排序保存到内存等等一系列的操作。下面是几个相关指令 sql_query \SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, \title, content \FROM doc…

C#给图片添加版权信息

现在越来越多的网站都喜欢将用户上传的图片加上网站的版权信息,不要以为那是用photoshop之类的图片处理软件加上去的,其实我们只要写一小段代码,就可以实现这个功能。 添加版权信息的原理其实挺简单:通过图片获取Graphics类的对象…

Python + 爬虫:可视化大屏帮你选粽子

来源 | 数据分析与统计学之美头图 | 下载于ICphoto端午节快要到了,旅游?回家?拜访亲友?少不了要带上粽子。那么,选择什么牌子的粽子呢?选择什么口味的粽子呢?选择什么价格区间呢?今年…

adviser vs mentor

研究生或博士生提到自己导师的时候是说adviser呢?还是mentor呢? 至少我认识一个Berkeley的博士是说adviser的。 另外,我的导师也是说adviser。 那还是说adviser吧……

T extends Serializable这是什么意思呢?看明白这个,你的问题就自然而然的明白了!...

1.转自:https://blog.csdn.net/liwenqiang758/article/details/8131185 自己动手丰衣足食!!! 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 这种参数类型可以用在类、接口和方法的创建中&a…

C#中switch语句注意

大家肯定对switch语句并不陌生,它能够让程序根据控制表达式的值,从多个动作中作出选择(从逻辑过程看,和多分支语句if-else有些相似)。在C和java中也有这一语句,不过在C#中,这一语句则有了些变化。先看下边一…

对Cost (%CPU) 粗略的理解

今天研究执行计划,看到执行计划里面有Cost (%CPU),我这边研究了一把,不知道对与否,拿出来晒晒在Oracle 10g中,Oracle 把CPU的cost也统计在执行计划中去了, 这和以前的8i,9i(9i其实已经开始了)有很大的不同。…

后疫情时代,RTC期待新的场景大爆发

整理 | 寇雪芹头图 | 下载于ICphoto出品 | AI 科技大本营(ID:rgznai100) 过去的一年中,新冠疫情悄然改变了社会发展和人们的生活,也助推了实时音视频(Real-Time Communication)技术的落地应用,数…