Thumbnail: Linux

CS6.NULL Lecture2

by on under Linux
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 .


Linux