本文为翻译
原文: https://www.trevorlasn.com/blog/10-essential-terminal-commands-every-developer-should-know
以下是一些能提升生产力的实用 Unix 终端命令。这些都是我最喜欢的命令。有时候,需要编写数小时代码才能完成的任务,使用终端几分钟就能搞定。
本文假设您已经熟悉基本命令如 rm、pwd 和 cd。
grep
需要在代码库中查找某个函数或变量的使用位置,或者筛选日志查找特定条目?grep 可以帮您完成这些任务。
grep 命令用于在文件中搜索特定模式。它就像一个超级搜索功能,可以深入文件内容进行查找。
grep 命令的基本语法如下:
➜ grep "let's find something" file.[txt,json,js,md,etc]
➜ grep "let's find something" file.[txt,json,js,md,etc]
不区分大小写搜索: 添加 -i 标志来忽略大小写差异。
➜ grep -i "REact" compiler/apps/playground/app/index.tsx
? '[DEV] React Compiler Playground'
: 'React Compiler Playground'
➜ grep -i "REact" compiler/apps/playground/app/index.tsx
? '[DEV] React Compiler Playground'
: 'React Compiler Playground'
统计出现次数: 使用 -c 标志来统计匹配行的数量。
➜ grep -c "React" compiler/apps/playground/app/index.tsx
➜ grep -c "React" compiler/apps/playground/app/index.tsx
分析日志: 如果您正在排查问题,可以使用 grep 在日志中查找特定的错误消息。
➜ grep -i "Operation not supported on socket" system.log
09/24 08:51:01 INFO :..settcpimage: Get TCP images rc - EDC8112I Operation not supported on socket.
➜ grep -i "Operation not supported on socket" system.log
09/24 08:51:01 INFO :..settcpimage: Get TCP images rc - EDC8112I Operation not supported on socket.
搜索多个模式: 您可以通过多次使用 -e 标志来搜索多个模式。
在 system.log 中匹配 "error" 或 "404"。
➜ grep -e "error" -e "404" system.log
npm error code E404
npm error 404 'trevorlasn.com@*' is not in this registry.
npm error A complete log of this run can be found in: /Users/trevorindreklasn/.npm/_logs/2024-08-20T16_41_32_846Z-debug-0.log
➜ grep -e "error" -e "404" system.log
npm error code E404
npm error 404 'trevorlasn.com@*' is not in this registry.
npm error A complete log of this run can be found in: /Users/trevorindreklasn/.npm/_logs/2024-08-20T16_41_32_846Z-debug-0.log
递归搜索: 要搜索目录及其子目录中的所有文件中的模式,使用 -r(或 —recursive)标志。
➜ grep -o -r "fs" node_modules | wc -l
22491
➜ grep -o -r "fs" node_modules | wc -l
22491
这将搜索指定目录及其子目录中的所有文件。-o 选项告诉 grep 只打印匹配的部分。
管道符 | 将左侧命令(grep)的输出作为右侧命令(wc -l)的输入。wc -l 计算并显示其输入的行数。
man
man 命令代表"manual"(手册)。它帮助您查找其他命令和程序的详细信息。
➜ man grep
NAME
grep, egrep, fgrep, rgrep, bzgrep, bzegrep, bzfgrep, zgrep,
zegrep, zfgrep – file pattern searcher
SYNOPSIS
grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num]
[-C num] [-e pattern] [-f file] [--binary-files=value]
[--color[=when]] [--colour[=when]] [--context=num]
[--label] [--line-buffered] [--null] [pattern] [file ...]
DESCRIPTION
The grep utility searches any given input files, selecting
lines that match one or more patterns. By default, a pattern
matches an input line if the regular expression (RE) in the
pattern matches the input line without its trailing newline.
An empty expression matches every line. Each input line that
matches at least one of the patterns is written to the standard
output.
grep is used for simple patterns and basic regular expressions
(BREs); egrep can handle extended regular expressions (EREs).
See re_format(7) for more information on regular expressions.
fgrep is quicker than both grep and egrep, but can only handle
fixed patterns (i.e., it does not interpret regular
expressions). Patterns may consist of one or more lines,
allowing any of the pattern lines to match a portion of the
input.
zgrep, zegrep, and zfgrep act like grep, egrep, and fgrep,
respectively, but accept input files compressed with the
compress(1) or gzip(1) compression utilities. bzgrep, bzegrep,
and bzfgrep act like grep, egrep, and fgrep, respectively, but
accept input files compressed with the bzip2(1) compression
utility.
The following options are available:
-A num, --after-context=num
Print num lines of trailing context after each match.
See also the -B and -C options.
...
➜ man grep
NAME
grep, egrep, fgrep, rgrep, bzgrep, bzegrep, bzfgrep, zgrep,
zegrep, zfgrep – file pattern searcher
SYNOPSIS
grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num]
[-C num] [-e pattern] [-f file] [--binary-files=value]
[--color[=when]] [--colour[=when]] [--context=num]
[--label] [--line-buffered] [--null] [pattern] [file ...]
DESCRIPTION
The grep utility searches any given input files, selecting
lines that match one or more patterns. By default, a pattern
matches an input line if the regular expression (RE) in the
pattern matches the input line without its trailing newline.
An empty expression matches every line. Each input line that
matches at least one of the patterns is written to the standard
output.
grep is used for simple patterns and basic regular expressions
(BREs); egrep can handle extended regular expressions (EREs).
See re_format(7) for more information on regular expressions.
fgrep is quicker than both grep and egrep, but can only handle
fixed patterns (i.e., it does not interpret regular
expressions). Patterns may consist of one or more lines,
allowing any of the pattern lines to match a portion of the
input.
zgrep, zegrep, and zfgrep act like grep, egrep, and fgrep,
respectively, but accept input files compressed with the
compress(1) or gzip(1) compression utilities. bzgrep, bzegrep,
and bzfgrep act like grep, egrep, and fgrep, respectively, but
accept input files compressed with the bzip2(1) compression
utility.
The following options are available:
-A num, --after-context=num
Print num lines of trailing context after each match.
See also the -B and -C options.
...
cat
cat 命令是"concatenate"(连接)的缩写。它用于显示文件内容、合并文件或创建新文件。
➜ trevorlasn.com git:(master) ✗ cat astro.config.mjs
import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
import tailwind from "@astrojs/tailwind";
import vercel from "@astrojs/vercel/static";
import partytown from "@astrojs/partytown";
// https://astro.build/config
export default defineConfig({
site: "https://www.trevorlasn.com",
integrations: [ mdx(), sitemap(), tailwind(), partytown({
config: {
forward: ["dataLayer.push"]
}
}), ],
output: "static",
adapter: vercel(),
});
➜ trevorlasn.com git:(master) ✗ cat astro.config.mjs
import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
import tailwind from "@astrojs/tailwind";
import vercel from "@astrojs/vercel/static";
import partytown from "@astrojs/partytown";
// https://astro.build/config
export default defineConfig({
site: "https://www.trevorlasn.com",
integrations: [ mdx(), sitemap(), tailwind(), partytown({
config: {
forward: ["dataLayer.push"]
}
}), ],
output: "static",
adapter: vercel(),
});
合并文件: cat 的一个关键特性是能够将多个文件合并成一个。例如,如果您想将 file1.txt 和 file2.txt 合并到 file3.txt,可以这样做:
➜ cat file1.txt file2.txt > file3.txt
➜ cat file1.txt file2.txt > file3.txt
上面的命令将 file1.txt 和 file2.txt 的内容合并到 file3.txt 中。> 运算符用于将合并的输出重定向到新文件。
创建新文件: 您也可以使用 cat 创建新文件。输入文本,完成后按 Ctrl+D 保存并退出。
➜ cat > newfile.txt
hey
➜ ls
newfile.txt
➜ cat newfile.txt
hey
➜ cat > newfile.txt
hey
➜ ls
newfile.txt
➜ cat newfile.txt
hey
cat 对于查看较小的文件很有帮助,但对于非常大的文件,它会一次性显示所有内容,可能会让人不知所措。在这种情况下,最好使用 less 或 head 等命令以更可控的方式查看文件。
head
在处理大文件时,您通常不需要看到所有内容。head 命令让您可以预览文件的前几行,而不是使用 cat 显示所有内容。
这对于检查 CSV 文件、日志或任何其他大型文本文件的结构特别有用。
默认情况下,head 显示文件的前 10 行:
➜ trevorlasn.com git:(master) ✗ head package-lock.json
{
"name": "trevorlasn.com",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "trevorlasn.com",
"version": "1.0.0",
"dependencies": {
➜ trevorlasn.com git:(master) ✗ head package-lock.json
{
"name": "trevorlasn.com",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "trevorlasn.com",
"version": "1.0.0",
"dependencies": {
如果需要更多或更少的行,可以使用 -n 选项指定确切的行数:
➜ trevorlasn.com git:(master) ✗ head -n 5 package-lock.json
{
"name": "trevorlasn.com",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
➜ trevorlasn.com git:(master) ✗ head -n 5 package-lock.json
{
"name": "trevorlasn.com",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
预览 CSV 表头: 对于 CSV 文件,head 非常适合快速检查表头或结构:
➜ head -n 1 username-password-recovery-code.csv
Username; Identifier;One-time password;Recovery code;First name;Last name;Department;Location
➜ head -n 1 username-password-recovery-code.csv
Username; Identifier;One-time password;Recovery code;First name;Last name;Department;Location
awk
awk 是一个强大的模式扫描和处理工具。它特别适用于操作和分析文本文件和数据流。
使用 awk,您可以过滤、提取和转换文件或命令输出中的数据。
awk 使用其关联数组高效地从各种来源提取和组合数据。假设您有两个 CSV 文件:
员工列表。
➜ cat employees.csv
ID,Name,Department
101,John Doe,Sales
102,Jane Smith,Engineering
103,Jim Brown,Sales
➜ cat employees.csv
ID,Name,Department
101,John Doe,Sales
102,Jane Smith,Engineering
103,Jim Brown,Sales
工资列表。
➜ cat salaries.csv
ID,Salary
101,50000
102,60000
103,55000
➜ cat salaries.csv
ID,Salary
101,50000
102,60000
103,55000
使用 awk 合并这些文件并显示每个员工的姓名和工资。
➜ awk -F',' '
NR==FNR {salaries[$1]=$2; next}
FNR==1 {next}
{print $2, salaries[$1]}
' salaries.csv employees.csv
John Doe 50000
Jane Smith 60000
Jim Brown 55000
➜ awk -F',' '
NR==FNR {salaries[$1]=$2; next}
FNR==1 {next}
{print $2, salaries[$1]}
' salaries.csv employees.csv
John Doe 50000
Jane Smith 60000
Jim Brown 55000
NR==FNR {salaries[$1]=$2; next}
:在处理第一个文件(salaries.csv
)时,将工资存储在关联数组中。员工 ID($1)是键,工资($2)是值。这只在第一个文件上运行。FNR==1 {next}
:跳过第二个文件(employees.csv)的表头行。{print $2, salaries[$1]}
:对于第二个文件(employees.csv)中的每一行,打印员工姓名($2)和数组中的工资(salaries[$1])。
您也可以将结果保存到新文件。
➜ awk -F',' '
NR==FNR {salaries[$1]=$2; next}
FNR==1 {next}
{print $2, salaries[$1]}
' salaries.csv employees.csv > combined.csv
➜ cat combined.csv
John Doe 50000
Jane Smith 60000
Jim Brown 55000
➜ awk -F',' '
NR==FNR {salaries[$1]=$2; next}
FNR==1 {next}
{print $2, salaries[$1]}
' salaries.csv employees.csv > combined.csv
➜ cat combined.csv
John Doe 50000
Jane Smith 60000
Jim Brown 55000
sed
sed 是 Stream Editor(流编辑器)的缩写,是一个强大的终端文本处理工具。它允许您在文件或数据流中查找、替换、插入或删除文本。
您可以用它进行快速编辑,而无需打开文本编辑器,这使其非常适合脚本编写和自动化。
替换文件中的单词或模式: 将"Trevor"替换为"John"。
➜ cat hello.md
My name is Trevor
➜ sed -i '' 's/Trevor/John/' hello.md
➜ cat hello.md
My name is Joh
➜ cat hello.md
My name is Trevor
➜ sed -i '' 's/Trevor/John/' hello.md
➜ cat hello.md
My name is Joh
如果要保存更改,使用 -i 选项。
打印特定行: 只打印文件中的特定行。
➜ trevorlasn.com git:(master) ✗ sed -n '2,4p' package-lock.json
"name": "trevorlasn.com",
"version": "1.0.0",
"lockfileVersion": 3,
➜ trevorlasn.com git:(master) ✗ sed -n '2,4p' package-lock.json
"name": "trevorlasn.com",
"version": "1.0.0",
"lockfileVersion": 3,
这会打印第 2 到 4 行。
正则表达式: sed 支持正则表达式,允许进行复杂的搜索和替换操作。例如,将所有数字替换为"X":
➜ cat combined.csv
John Doe 50000
Jane Smith 60000
Jim Brown 55000
➜ sed 's/[0-9]/X/g' combined.csv
John Doe XXXXX
Jane Smith XXXXX
Jim Brown XXXXX
➜ cat combined.csv
John Doe 50000
Jane Smith 60000
Jim Brown 55000
➜ sed 's/[0-9]/X/g' combined.csv
John Doe XXXXX
Jane Smith XXXXX
Jim Brown XXXXX
批量重命名文件: 假设您有多个扩展名为 .txt 的文件,想要将它们重命名为 .md。
➜ ls
1.txt 2.txt 3.txt
➜ for file in *.txt; do
mv "$file" "$(echo "$file" | sed 's/.txt$/.md/')"
done
➜ ls
1.md 2.md 3.md
➜ ls
1.txt 2.txt 3.txt
➜ for file in *.txt; do
mv "$file" "$(echo "$file" | sed 's/.txt$/.md/')"
done
➜ ls
1.md 2.md 3.md
sed 非常灵活,这些例子只是冰山一角。
tail
tail 是 head 的对应命令。它允许您查看文件的最后几行,而不是开头。它通常用于监控日志文件或检查文档的结尾。默认情况下,tail 显示文件的最后 10 行。
➜ trevorlasn.com git:(master) ✗ tail package.json
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.57.0",
"eslint-plugin-astro": "^0.32.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"typescript": "^5.4.2"
}
}
➜ trevorlasn.com git:(master) ✗ tail package.json
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.57.0",
"eslint-plugin-astro": "^0.32.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"typescript": "^5.4.2"
}
}
查看更多或更少的行: 您可以使用 -n 选项调整显示的行数。
➜ trevorlasn.com git:(master) ✗ tail -n 15 package.json
"astro": "^4.13.3",
"clsx": "^2.1.0",
"sharp": "^0.33.3",
"tailwind-merge": "^2.2.2",
"tailwindcss": "^3.4.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.57.0",
"eslint-plugin-astro": "^0.32.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"typescript": "^5.4.2"
}
}
➜ trevorlasn.com git:(master) ✗ tail -n 15 package.json
"astro": "^4.13.3",
"clsx": "^2.1.0",
"sharp": "^0.33.3",
"tailwind-merge": "^2.2.2",
"tailwindcss": "^3.4.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.57.0",
"eslint-plugin-astro": "^0.32.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"typescript": "^5.4.2"
}
}
实时文件监控: tail 最强大的功能之一是 -f 选项,它允许您实时跟踪文件的变化。这对于实时查看日志文件特别有用。
➜ tail -f 1.md
11
Changing file
➜ tail -f 1.md
11
Changing file
当新行添加到 1.md 时,tail 会自动显示它们。
chmod
每个文件都有三组权限:所有者、组和其他用户。这些通常以 rwxr-xr— 这样的格式表示。
- r: 读取权限
- w: 写入权限
- x: 执行权限
➜ ls -l sensitive.md
-rw-r--r--@ 1 trevorindreklasn staff 0 Aug 21 15:22 sensitive.md
➜ ls -l sensitive.md
-rw-r--r--@ 1 trevorindreklasn staff 0 Aug 21 15:22 sensitive.md
文件权限 -rw-r—r—
表示:
- 所有者(trevorindreklasn): 具有读取(r)和写入(w)权限。
- 组(staff): 具有读取(r)权限。
- 其他用户: 具有读取(r)权限。
@ 符号表示该文件具有扩展属性,这些是超出标准文件权限的额外元数据。
文件权限控制谁可以读取、写入或执行文件,通过防止未授权用户修改或查看敏感数据来确保安全性和适当的访问管理。
要限制对 sensitive.md 的访问,使只有 root 用户或超级管理员可以查看和写入,您可以使用 chmod 命令修改文件的权限。
首先,确保文件由 root 用户或超级管理员拥有。更改所有权可能需要 sudo:
➜ ls -l sensitive.md
-rw-r--r--@ 1 root staff 0 Aug 21 15:22 sensitive.md
➜ sudo chown root:admin sensitive.md
➜ ls -l sensitive.md
-rw-r-----@ 1 root admin 0 Aug 21 15:22 sensitive.md
➜ sudo chmod 600 sensitive.md
➜ textfiles ls -l sensitive.md
-rw------- 1 root admin 0 Aug 21 15:22 sensitive.md
➜ ls -l sensitive.md
-rw-r--r--@ 1 root staff 0 Aug 21 15:22 sensitive.md
➜ sudo chown root:admin sensitive.md
➜ ls -l sensitive.md
-rw-r-----@ 1 root admin 0 Aug 21 15:22 sensitive.md
➜ sudo chmod 600 sensitive.md
➜ textfiles ls -l sensitive.md
-rw------- 1 root admin 0 Aug 21 15:22 sensitive.md
只有所有者(root)具有读取和写入权限。而组和其他用户没有任何权限。这限制了文件的访问,使其只能由所有者读取和写入。
不正确的文件权限可能导致安全问题或系统问题
未授权访问: 如果包含敏感信息(如密码或财务数据)的文件设置了过于宽松的权限(例如 chmod 777),系统上的任何人都可以读取或修改它。这可能导致数据泄露或未授权访问敏感信息。
恶意软件安装: 如果文件或目录对所有用户都有写入权限(例如 chmod 777),攻击者可能会利用它来放置恶意脚本或软件,可能会危及整个系统。
数据损坏: 如果应该只读的文件(例如日志或系统配置)被意外授予写入权限,用户或应用程序可能会无意中损坏或删除关键数据,导致系统不稳定或丢失重要信息。
xargs
xargs 命令使用其他命令的输入构建和运行命令。它用于将项目列表作为参数传递给另一个命令。
假设您有一个要删除的文件列表。
➜ ls
1.txt 2.txt 2.md 3.md sensitive.md
# Find all .txt files and delete them
➜ find . -name "*.txt" | xargs rm
➜ ls
2.md 3.md sensitive.md
➜ ls
1.txt 2.txt 2.md 3.md sensitive.md
# Find all .txt files and delete them
➜ find . -name "*.txt" | xargs rm
➜ ls
2.md 3.md sensitive.md
您可以使用 xargs 将文件列表传递给 rm,而不是一个一个地删除它们。
find . -name "*.tmp" | xargs rm
find . -name "*.tmp" | xargs rm
创建多个目录: 如果您在文件中有目录名称列表,想要创建所有这些目录,可以使用 xargs 和 mkdir。
➜ cat dirs.txt
src
temp
utils
public
➜ ls
2.md 3.md dirs.txt sensitive.md
# Creates each directory listed in the file.
➜ cat dirs.txt | xargs mkdir
➜ ls
2.md dirs.txt sensitive.md temp
3.md public src utils
➜ cat dirs.txt
src
temp
utils
public
➜ ls
2.md 3.md dirs.txt sensitive.md
# Creates each directory listed in the file.
➜ cat dirs.txt | xargs mkdir
➜ ls
2.md dirs.txt sensitive.md temp
3.md public src utils
压缩文件: 如果您有多个要使用 gzip 压缩的文件,可以使用 xargs 将文件名传递给 gzip。
# Compresses all .log files in the current directory
ls *.log | xargs gzip
# Compresses all .log files in the current directory
ls *.log | xargs gzip
find
在文件系统中基于各种条件搜索和定位文件和目录。它高度可定制,可以与其他命令结合使用来完成复杂任务。
find [path] [expression]
find [path] [expression]
find 命令在 node_modules 目录中搜索"astro"的出现,返回具有该名称的文件和目录的路径,包括可执行文件和包文件。
➜ trevorlasn.com git:(master) ✗ find node_modules -name "astro"
node_modules/.bin/astro
node_modules/astro
node_modules/astro/dist/runtime/server/render/astro
➜ trevorlasn.com git:(master) ✗ find node_modules -name "astro"
node_modules/.bin/astro
node_modules/astro
node_modules/astro/dist/runtime/server/render/astro
清理旧日志文件: 定期删除超过一个月的日志文件以释放磁盘空间。
➜ find /var/log -type f -name "*.log" -mtime +30 -delete
➜ find /var/log -type f -name "*.log" -mtime +30 -delete
备份重要文件: 从主目录中定位并复制所有 .docx 文件到备份位置。
➜ find ~/Documents -name "*.docx" -exec cp {} /path/to/backup/ \;
➜ find ~/Documents -name "*.docx" -exec cp {} /path/to/backup/ \;
find 命令非常灵活,可以根据各种文件管理任务进行定制。
值得提及的其他命令
jq: 像使用 sed、awk、grep 一样轻松地切片、过滤、映射和转换结构化数据。
cut: 用于从文件的每一行中删除部分内容的命令。
netstat: 用于显示网络连接、路由表和接口统计信息的网络工具。
ping: 用于测试 IP 网络上主机的可达性并测量往返时间的工具。
ifconfig: 用于配置网络接口的命令(已被 ip 取代)。
telnet: 使用 Telnet 协议通过网络与远程主机交互的程序。
sftp: 使用 SSH 协议的交互式文件传输程序。
wget: 使用 HTTP 和 FTP 从万维网检索文件的网络工具。
ps: 显示有关运行进程的信息。
top: 用于实时查看和管理运行进程的任务管理器。
kill: 用于向进程发送信号的命令,通常用于终止进程。
comm: 逐行比较两个已排序文件的命令。