1.对于这门课程,你需要使用一个 Unix Shell,例如 Bash 或 ZSH。如果你使用的是 Linux 或 macOS,则不需要做任何特殊设置。如果你使用的是 Windows,则需要确保你运行的不是 cmd.exe 或 PowerShell;你可以使用 Windows Subsystem for Linux(WSL)或 Linux 虚拟机来使用 Unix 风格的命令行工具。为了确认你运行的是合适的 Shell,可以尝试执行命令echo $SHELL。如果输出类似于/bin/bash或/usr/bin/zsh,则说明你运行的是正确的程序。
2.ls命令中的-l选项有什么作用?运行ls -l /并检查输出。每一行最前面的 10 个字符分别表示什么意思?
1. 使用长列表(long listing)格式。2. 第一个字符表示文件的类型,后面的9个字符表示文件的权限,包括所有者权限、所属组权限以及其他用户权限。3.在命令find ~/Downloads -type f -name "*.zip" -mtime +30中,*.zip是一个“glob”。什么是 glob?创建一个测试目录并放入一些文件,然后尝试使用ls *.txt、ls file?.txt和ls {a,b,c}.txt等模式进行实验。参见 Bash 手册中的Pattern Matching(模式匹配)。
1. glob 是 Shell 中的一种模式匹配方法。`*`匹配任意字符串,`?`匹配任意单个字符,`[...]`匹配方括号中包含的任意一个字符。4.单引号('single quotes')、双引号("double quotes")和$'ANSI quotes'有什么区别?编写一个命令,输出一个包含字面量$、!和换行符的字符串。参见Quoting(引用)。
单引号会保留引号内每个字符的字面值。双引号会保留引号内所有字符的字面值,但`$`、`````、`\`以及在启用历史展开时的`!` 除外。ANSI 引号被视为一种特殊的单引号,其中字符串中的反斜杠转义字符会按照 ANSI C 标准进行展开和替换。5.Shell 有三个标准流:stdin(0)、stdout(1)和 stderr(2)。运行ls /nonexistent /tmp,并将 stdout 重定向到一个文件,将 stderr 重定向到另一个文件。如何将它们都重定向到同一个文件?参见Redirections(重定向)。
ls/nonexistent /tmp2>error.log>output.logls/nonexistent /tmp>output.log2>&16.$?保存上一条命令的退出状态(0 表示成功)。&&仅在前一条命令成功时运行下一条命令;||仅在前一条命令失败时运行下一条命令。编写一条单行命令,仅在/tmp/mydir不存在时创建它。参见Exit Status(退出状态)。
ls/tmp/mydir||mkdir/tmp/mydir7.为什么cd必须作为 Shell 的内建命令,而不能是一个独立的程序?(提示:思考子进程能够和不能够影响父进程的哪些内容。)
子进程永远不能修改其父进程的环境。如果`cd`是位于`/bin/cd`的一个独立程序:1. 你输入`/bin/cd /tmp`。2. Shell 创建(fork)一个子进程来运行`/bin/cd`。3. 子进程成功将它自己的当前工作目录切换到`/tmp`。4.`/bin/cd`程序执行结束并退出。5. 你返回到父 Shell,但它的工作目录并没有改变,因为父进程与子进程的环境是完全隔离的。8.编写一个脚本,将文件名作为参数($1),并使用test -f或[ -f ... ]检查该文件是否存在。根据文件是否存在输出不同的信息。参见Bash Conditional Expressions(Bash 条件表达式)。
#!/bin/bashif[-z"$1"];thenecho"no input"exit1fiif[-f"$1"];thenecho"exist"elseecho"doesn't exist"fi9.将上一题中的脚本保存为一个文件(例如check.sh)。尝试使用./check.sh somefile运行它,会发生什么?然后执行chmod +x check.sh再次运行。为什么这一步是必须的?(提示:比较chmod前后ls -l check.sh的输出。)
$ ./check.sh2.txt zsh: permission denied: ./check.sh $chmod+x ./check.sh $ ./check.sh2.txt exist10.如果在脚本中为set添加-x选项,会发生什么?使用一个简单的脚本进行测试,并观察输出。参见The Set Builtin(set 内建命令)。
$ ./check.sh2.txt +'['-z2.txt']'+'['-f2.txt']'+echoexist exist会打印每条执行的命令及其展开后的变量。
11.编写一条命令,将一个文件复制为一个带有当天日期作为文件名后缀的备份文件(例如notes.txt→notes_2026-01-12.txt)。(提示:$(date +%Y-%m-%d))。参见Command Substitution(命令替换)。
cpnotes.txt"notes_$(date+%Y-%m-%d).txt"12.修改课程中的 flaky test 脚本,使它接受测试命令作为参数,而不是将cargo test my_test写死。(提示:使用$1或$@)。参见Special Parameters(特殊参数)。
将cargotestmy_test 替换为"$@"。13.使用管道统计你的 Home 目录中最常见的 5 种文件扩展名。(提示:组合使用find、grep或sed或awk、sort、uniq -c和head。)
find~-typef|grep-E'\.[^./]+$'-o|awk'{print tolower($0)}'|sort|uniq-c|sort-nr|head-n514.xargs会将标准输入中的每一行转换为命令参数。结合使用find和xargs(不要使用find -exec),查找目录中的所有.sh文件,并使用wc -l统计每个文件的行数。附加要求:正确处理文件名中包含空格的情况。(提示:使用-print0和-0)。参见man xargs。
find.-name"*.sh"-print0|xargs-0wc-l15.使用curl获取课程网站(https://missing.csail.mit.edu/)的 HTML,并通过管道传递给grep,统计网站中列出了多少节课。(提示:寻找一个每节课只出现一次的模式;使用curl -s关闭进度输出。)
curl-shttps://missing.csail.mit.edu/|grep-o'/2026/[a-z0-9\-]\+/'|sort|uniq|wc-l16.jq是一个功能强大的 JSON 数据处理工具。使用curl获取https://microsoftedge.github.io/Demos/json-dummy-data/64KB.json中的示例数据,然后使用jq提取所有version大于 6 的人的name。(提示:先执行jq .查看 JSON 结构,再尝试jq '.[] | select(...) | .name'。)
curl-s"https://microsoftedge.github.io/Demos/json-dummy-data/64KB.json"|jq'.[] | select(.version >= 6) | .name'17.awk可以根据列值筛选行并修改输出。例如,awk '$3 ~ /pattern/ {$4=""; print}'会打印第三列匹配pattern的所有行,同时省略第四列。编写一条awk命令,仅打印第二列大于 100 的行,并交换第一列和第三列。使用以下数据进行测试:
printf'a 50 x\nb 150 y\nc 200 z\n'printf'a 50 x\nb 150 y \nc 200 z\n'|awk'$2 > 100 {t=$1;$1=$3;$3=t;print}'18.分析课程中 SSH 日志处理管道:解释每一步分别完成什么操作。然后编写一个类似的管道,从~/.bash_history(或~/.zsh_history)中找出你最常使用的 Shell 命令。
cat~/.zsh_history|awk-F';''{print $2}'|awk'{print $1}'|sort|uniq-c|sort-nr|head-n10