![Thumbnail: Linux](https://i.loli.net/2021/10/26/6lQthgjoL3PG1Ai.png)
CS6.NULL Lecture2
4 minute read
变量声明
shell 编程中空格非常重要,不能随便加减,想要输出变量的值时需要在变量前加上$
.
foo=bar
echo $foo # output is bar
foo=$(pwd)
echo foo
# 会输出 pwd 打印的内容
""
与 ''
都可以定义字符串,但是 ""
可以表示输出变量的值,类似格式化输出,而 ''
则只会按原样输出。
# output is: value is bar
echo "value is $foo"
# output is: value is $foo
echo 'value is $foo'
shell 函数
shell 函数可以视为一个简单的脚本指令,调用函数即执行函数内一系列操作
# 这个函数的作用是建立一个文件夹,并进入
mcd () {
mkdir -p "$1" # "$1" 类似 "argv"
cd "$1"
}
# 通过 source mcd.sh 来编译该文件
# mcd "" 即可直接调用
$1
为脚本的名字
$1 ~ $9
为第一至第九个参数
$?
从上一条命令获得错误代码
$_
获得上一条指令的最后一个参数
$#
总共给多少个参数
$$
the process id of this command that is running
$@
expand to all arguments
!!
获得上一条指令
逻辑运算符
||
会先检查左边的,若左边为假则执行右边的
# output is "Oops fail"
false || echo "Oops fail"
# output is nothing
true || echo "will not be printed"
&&
只有当左边的为真时才会执行右边的
# output is "Things went well"
true && echo "Things went well"
# noting will be printed
false && echo "this will not be printed"
;
可以在一行内串联命令,命令彼此之间不会影响
false ; echo "This will always print"
循环与 if
echo "Starting program at $(date)" # Date will be substitued
echo "Running program $0 with $# arguments with pid $$"
for file in "$@"; do
grep foobar "$file" > /dev/null 2> /dev/null
# when pattern is not found, grep has exit status
# we redirect STDOUT and STDERR to a null register since we do ____ about them
if [["$? -ne 0"]]; then # `-ne` means not equal
echo "File $file does not have any foobar, adding one"
echo "# foobar" >> "$file"
fi
done
一些小技巧
?
会从 1 到 9 遍历 (?
will only expand to a single one)
# will print project1, project2, project3.... till no more
ls project?
*
可以用在查找相同后缀名的文件
# will print all .sh files
ls *.sh
# 比较 foo 和 bar 文件夹内的不同
diff < (ls foo) < (ls bar)
# 检查文件语法
shellcheck mcd.sh
# 帮助了解指令的作用
man ls
tldr convert
# 显示历史指令
history
history 1 # 从头显示历史指令
history 1 | grep convert # 从头显示所有包含 convert 的指令
{}
有类似合并 (combine) 的作用
# the following 2 lines work the same
convert image.png image.jpg
convert image.{png,jpg}
touch foo{,1,2,10}
touch foo foo1 foo2 foo10
# 在 project1 与 project2 下的这个目录里各自分别创建 test1,2,3.py 三个文件
touch project{1,2}/src/test/test{1,2,3}.py
# 在 foo 下创建从 a ~ j 个文件
touch foo/{a..j}
调用 python 脚本程序
告诉 shell 用 python 运行此程序
#!/usr/bin/env python # 使用环境变量以适配其他机器
import sys
for arg in reversed(sys.argv[1:]):
print(arg)
关于查找
# 找到对应文件的路径
# . 表示在当前路径下
# -name src 名称为 src
# -type d 类型为 directory
find . -name src -type d
# 找出所有 .py 文件的路径
# -path '**/tests/*py' ** 省略了 tests 之前的路径
# *.py 表示所有以 .py 结尾的文件
# -type f 表示查找类型为 file
find . -path '**/test/*py' -type f
# 可缩写为
fd ".*py"
# 找到当前目录下所有的 .tmp 文件并对他们执行 rm 指令
find . -name "*.tmp" -exec rm {} \;
# 查找文件内的内容
# 在 mcd.sh 中查找 foobar
grep foobar mcd.sh
# 在当前目录下查找所有的 foobar
grep -R foobar .