命令行

GUI、CLI

CSGO就不是命令行软件

  • GUI: *Command-Line Interface,命令行界面,*命令行界面用鼠标双击会跳窗口的软件
  • CLI: Graphical User Interface,图形用户界面在终端里敲键盘才能用的软件
Type GUI CLI
浏览器 Chrome/Firefox w3m/lynx
图像处理 PhotoShop ImageMagick
视频编辑 Pr/Davinci resolve FFmpeg
文本编辑 VSCode/Sublime Vim/TECO

为什么要使用命令行

因为我们用计算机的目的不同:程序员要写程序

  • 而命令行比GUI更高效

比如apt install gcc一行就能安装完整的C语言编译工具

*example:*比较两个文件是否相同

  • 命令行:

    1
    2
    3
    文本文件的比较:vimdiff file1 file2
    非文本文件的比较:diff file1 file2
    很大的文件:md5sum file1 file2
  • GUI:

    先找一个有这个功能的软件,然后下载,然后安装,然后看看怎么用,然后比较

更重要的是,有些复杂的事情GUI几乎做不了

*example:*列出一个C语言项目中所有被包含过的头文件

  • GUI:

    好像没法做

  • 命令行:

    1
    find . -name "*.[ch]" | xargs cat | grep "^#include" | sort | uniq 

命令行的优点:

  1. 每个小工具只做一件事
  2. 小工具采用文本进行输入输出,从而易于使用
  3. 通过小工具之间的组合来解决复杂问题

文本编辑

  • Vim / Emacs

Vim

[菜鸟教程](Linux vi/vim | 菜鸟教程)

特点:命令式编程。Vim 共分为三种模式,命令模式(Command Mode)、输入模式(Insert Mode)和命令行模式(Command-Line Mode)

命令模式

  • h,j,k,l:左,下,上,右
  • i:切换到输入模式,在光标当前位置开始输入文本
  • x:删除当前光标所在处的字符。
  • ::切换到底线命令模式,以在最底一行输入命令。
  • a:进入插入模式,在光标下一个位置开始输入文本。
  • o:在当前行的下方插入一个新行,并进入插入模式。
  • O:在当前行的上方插入一个新行,并进入插入模式。
  • dd:剪切当前行。
  • yy:复制当前行。
  • p:(小写)粘贴剪贴板内容到光标下方。
  • P:(大写)粘贴剪贴板内容到光标上方。
  • u:撤销上一次操作。
  • Ctrl + r:重做上一次撤销的操作。
  • :w:保存文件。
  • :q:退出 Vim 编辑器。
  • :q!:强制退出Vim 编辑器,不保存修改。

Emacs

[Emacs教程——知乎](专业 Emacs 入门(一) - 知乎)

**为什么有必要了解一些Emacs键位:**因为一些发行版自带的终端不支持Vim键位而支持Emacs快捷键

  • Ctrl+a:跳转句首
  • Ctrl+e:跳转句末
  • Alt+fAlt+b:在单词间跳转
  • Alt+c:跳转到下一个单词,并将前一个单词的首字母大写

文件管理

Linux常用命令

  • ls:列出当前目录中的文件和子目录

  • touch <filename> :创建新文件

  • echo <string>:输出字符串

  • rm:删除文件或目录

    1
    2
    rm file_name
    rm -r directory_name # 递归删除目录及其内容
  • mkdir:创建新目录

    1
    mkdir directory_name
  • mv:移动或重命名文件或目录

    1
    mv old_name new_name
  • pwd:显示当前工作目录的路径

  • cat:连接和显示文件内容

进程管理

  • Ctrl+z:将一个正在前台执行的命令挂起

  • bg:将一个在后台暂停的命令,变成继续执行

  • jobs:查看当前有多少在后台运行的命令

  • fg:将后台中的命令调至前台继续运行

  • kill -9 <PID>:强制结束进程

  • ps aux:显示所有进程

  • top:实时监视系统资源(Ctrl+c退出)

  • htop:更友好的进程监视器(Ctrl+c退出)

输入输出

1
2
3
重定向
管道
xargs

重定向

改变目的地

改变命令的标准输入、标准输出和标准错误的默认目的地

输入重定向:

  • <:将文件的内容作为命令的输入

输出重定向:

  • >:将命令的输出重定向到文件中(覆盖原有内容
  • >>:将命令的输出追加到文件末尾

管道

连接输入输出

|:用于连接程序间输入输出的缓冲区,将一个命令的标准输出(stdout)直接连接到另一个命令的标准输入

  • |左边命令的输出就会作为|右边命令的输入

  • 可连续使用

    example:

    1
    2
    3
    # 计算 /bin 目录下的文件数量
    ls /bin | wc -l
    > 907

xargs

xargs:将标准输入转变为命令的参数

1
2
echo "a.c b.c c.c" | xargs  rm
rm "a.c b.c c.c"

通配符、正则表达式

通配符

通配符 功能 示例
* 匹配多个字符 *.txt匹配所有以.txt结尾的文件
? 匹配任意单个字符 file?.txt匹配file1.txtfilea.txt
[] 匹配括号中的任意字符 file[1-2].txt匹配file1.txtfile2.txtfile3.txt
[!] 匹配不在括号中的任意字符 file[!1-3].txt匹配除file1.txtfile2.txtfile3.txt的文件
{} 匹配指定的字符串 file{1,2}.txt匹配file1.txtfile2.txt

正则表达式

POSIX / Python & Perl / grep & egrep使用规范不一样,这里先略过

阅读文档

东西好多,我记不住/学不会怎么办?

最重要的Linux命令:man

  • 查阅命令/库函数/系统文件等内容的手册
  • man man:学习如何RTFM(Read The Friendly Manual)
  • man ls:查看如何使用ls命令

如何学习正则表达式?:man 7 regex

手册上没有怎么办?

基本上不太可能,如果真的没有:

  • Search The Friendly Web(Google、StackOverflow)
  • Ask The Friendly LLM(ChatGPT)
  • Read The Source Code

自动化、脚本

自动化

我们通过小工具的组合来解决复杂问题

example:

1
find . -name "*.[ch]" | xargs cat | grep "^#include" | sort | uniq 
  • find . -name "\*.[ch]":在当前目录查找所有以.c.h结尾的文件,并将结果通过管道传给下一条命令
  • xargs cat:运用xargs打印这些内容,并将结果通过管道传给下一条命令
  • grep "^#include":用grep查找所有以#include开头的内容,并将结果通过管道传给下一条命令
  • sort:对上面的结果进行排序,并将结果通过管道传给下一条命令
  • uniq:对上面的结果进行去重

脚本

把命令写到一个文件里面

  • 可以重复执行,不用每次都手动输入了
  • 可以被其他脚本调用,自动化工作
  • 效率提升

Windows 批处理文件 / Powershell:

Unix Bash/Zsh/Fish

Unix 是一种操作系统的设计理念和技术规范,Bash、Zsh 和 Fish 都是 Unix 系统(包括 Linux 和 macOS)中使用的命令行解释器(shell)

  • Bash: Linux 系统中默认的 Shell,bash 的特点是简单而实用
  • **Zsh:**zsh 是一个功能更为强大的 Shell,提供命令补全、自动纠错、语法高亮等丰富的特性,可定制性也更好
  • Fish:(Friendly Interactive Shell)相对于 bash 和 zsh 来说比较新的 Shell。主要特点是易于使用、友好、可定制性好等。它提供了很好的操作体验,包括语法高亮、命令补全等功能。

命令行的本质

工具类型的分布:

大部分是可执行文件(ELF),小部分是脚本

Linux 实践

在 Windows 上运行 Linux

WSL

Windows Subsystem for Linux

  • 性能:由于WSL直接在Windows内核之上运行Linux二进制文件,它提供了接近原生的性能,特别是在I/O操作方面有了显著改进(尤其是在WSL 2中)。
  • 易用性:非常易于安装和使用,只需通过Microsoft Store下载所需的Linux发行版并按照提示进行设置即可。
  • 资源使用:因为不需要虚拟化整个操作系统,所以资源消耗相对较低。
  • 适用场景:适合需要在Windows环境中运行Linux命令行工具的开发者,特别是对于那些想要快速启动Linux环境而无需管理完整虚拟机的人。

虚拟机

如 VMware, VirtualBox

  • 性能:虽然现代虚拟化技术已经相当高效,但与WSL相比,虚拟机仍然会带来一定的性能开销,尤其是在图形处理和I/O密集型任务中。
  • 易用性:安装过程较为复杂,需要配置虚拟硬盘、内存分配等参数,不过一旦设置完成,用户体验与实际物理机相似。
  • 资源使用:需要更多的系统资源,包括CPU、内存和磁盘空间,因为它实际上是在模拟一个完整的操作系统环境。
  • 适用场景:适用于需要在一个完全隔离的环境中测试软件或运行Linux桌面应用的情况。

Docker

  • 性能:Docker容器共享主机系统的内核,因此其性能损失极小,非常适合部署应用程序和服务。
  • 易用性:对于熟悉容器概念的用户来说,Docker易于使用且功能强大,但它可能对初学者不太友好。
  • 资源使用:比虚拟机更轻量,因为它不虚拟化整个操作系统层。
  • 适用场景:主要用于开发和部署应用程序,尤其是微服务架构的应用程序。

双系统

Dual Boot:双系统启动

  • 性能:提供完全的原生Linux体验,没有性能损失。
  • 易用性:安装过程复杂,涉及硬盘分区和引导加载程序配置,而且每次只能运行一个操作系统。
  • 资源使用:取决于你如何分配硬盘空间给两个系统,通常需要为每个系统预留足够的存储空间。
  • 适用场景:适合那些需要全面访问Linux功能,包括硬件支持、图形界面等,并愿意接受切换操作系统的不便之处的用户。

安装WSL

开启CPU虚拟化

Windows搜索栏 -> 任务管理器 -> 性能 -> CPU

开启Windows功能

Windows搜索栏 -> 控制面板 -> 程序 -> 程序和功能 ->启用或关闭Windows功能

打开:

  1. 适用于Linux的Windows子系统
  2. 虚拟机平台(Virtual Machine Platform)

安装

Windows搜索栏 -> 命令提示符 ->右键“以管理员身份运行”:

1
2
wsl --install --web-download 
# 默认下载Ubuntu

下载其他Linux版本:

1
2
wsl --list --online
wsl --install <版本名称> --web-download

后按提示启动Ubuntu,设置用户名、密码

卸载

1
wsl --unregister <版本名称>

Linux配置 VSCode C/C++开发环境

[Linux/Ubuntu中VSCode配置C++/C环境](Linux/Ubuntu中Vs Code配置C++/C环境)

  1. 安装扩展WSL
  • sudo apt update:更新软件包列表及其版本
  • sudo apt install build-essential gdb:包括但不限于 GCC (GNU Compiler Collection)、G++ (GCC 的 C++ 编译器)、make 等
  1. 远程资源管理器 -> WSL目标 ->连接Ubuntu

  2. 安装插件:(运行)

    • C/C++ (C/C++ Extension Pack)
    • Code Runner

    先写一段代码运行,并选择编译器,自动生成.vscode文件

  3. 配置调试文件

    (现在除非是自定义调试,其实可以不需要了,直接右上角调试即可)

    在.vscode下配置文件launch.jsontasks.json(没有就新建)

    launch.json:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    {
    "version": "0.2.0",
    "configurations": [
    {
    "name": "C/C++",
    "type": "cppdbg",
    "request": "launch",
    "program": "${fileDirname}/${fileBasenameNoExtension}",
    "args": [],
    "stopAtEntry": false,
    "cwd": "${workspaceFolder}",
    "environment": [],
    "externalConsole": false,
    "MIMode": "gdb",
    "preLaunchTask": "compile",
    "setupCommands": [
    {
    "description": "Enable pretty-printing for gdb",
    "text": "-enable-pretty-printing",
    "ignoreFailures": true
    }
    ]
    }
    ]
    }

    task.json:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    {
    "version": "2.0.0",
    "tasks": [{
    "label": "compile",
    "command": "g++",
    "args": [
    "-g",
    "${file}",
    "-o",
    "${fileDirname}/${fileBasenameNoExtension}"
    ],
    "problemMatcher": {
    "owner": "cpp",
    "fileLocation": [
    "relative",
    "${workspaceRoot}"
    ],
    "pattern": {
    "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
    "file": 1,
    "line": 2,
    "column": 3,
    "severity": 4,
    "message": 5
    }
    },
    "group": {
    "kind": "build",
    "isDefault": true
    }
    }
    ]
    }

    这样你就可以用左边的运行和调试了