这是一个个人笔记的收录处,乐观地看,我会不断更新它来收录新内容。
Shell Script 中的控制语法
命令替换 Command Substitution
命令替换的方法为反引号 `command`
或者$(command)
,将 command 的执行结果(输出)放在原处。例如:
get_username() {
echo "john"
}
username=$(get_username)
DATE=$(date)
算术求值
形如 expr 11 / 2
或者 $((1 + 3))
。将算术求值和命令替换结合在一起的例子:
calculate_sum() {
echo $(( $1 + $2 )) # arithmetic evaluation, not command substitution.
}
result=$(calculate_sum 5 7) # command substitution
echo "The sum is: $result" # 12
注意,算术求值默认使用整型运算。所以 expr 11 / 2
会打印出 5。
接收参数
$2
或者 ${2}
用来代指第二个参数,这在上面的例子中已经体现了。对于 shell script 来说,$0
是 shell script 的文件名。$@
是所有参数。
echo $0
for arg in "$@"; do
echo "argument" ${arg}
if [[ ${arg} == "--task_dir" ]]; then
echo "\${2}" "${2}"
fi
done
如果运行上述脚本 ./loop_all.sh C --task_dir A B
,则预期的输出为
./loop_all.sh
argument C
argument --task_dir
${2} --task_dir
argument A
argument B
常见运算符
整型比大小:-eq -ne -gt -lt -ge -le。注:只支持作为条件,在 square bracket 中使用,如下例:
if [$a -ne $b] then
echo "not equal"
fi
逻辑运算符:-o (or), -a (and), !, &&, ||。例:if [[ $a -lt 100 && $b -gt 100 ]]
[ -z $a ] 检测字符串长度是否为零,[ -n “$a” ] 检查字符串长度是否不为零。单括号和双括号的区别在这里。
还有文件测试运算符:-b (is block device?), -c (is character device?), -d (is directory?), -f (is regular file nor dir or device?), -g, -k, -p, -u, -{r,w,x}, -s, -e (file exists?)
常用 Linux 命令备忘录
cd 和 sudo
cd 是 shell 内置的命令,并不对应非可执行文件(which cd
返回空)。
sudo 工作的原理是 fork 一个进程出来,execve 执行要执行的可执行文件。/usr/bin/sudo 的权限位是 -rwsr-xr-x,拥有者是 root:root,这保证任何用户可以执行 sudo,而执行 sudo 产生的进程的 UID 为 root,拥有足够的权限。
由于 cd 不对应可执行文件,因此 sudo cd
会报错 sudo: cd: command not found。
find
find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]
概要:以 starting-point 为根出发遍历文件树,依照 expression 中列出的标准匹配文件或文件夹,并对成功匹配的文件或文件夹做出相应行为。
starting-point 是一个列表。例如你可以执行 find dir1 dir2
expression 由测试(Tests)、行为(Actions)、运算符(Operators)等构成。
find 中的测试
测试形如 -testname,通常需要传入参数。对于数值参数 n,传入 +n 代表要求大于 n,-n 代表要求小于 n,n 代表刚好等于 n。
-amin n: 最近访问时间距离当前的分钟数
-atime n: 最近访问日期距离今天的天数
-cmin n: 最近一次元信息修改时间距离当前的分钟数
-ctime n: 最近一次元信息修改日期距离今天的天数
-empty: 文件或文件夹为空
-executable:是可执行文件或可穿过的文件夹
-iname pattern:等价于不区分大小写的 -name
-mmin n: 最近一次文件内容修改时间距离当前的分钟数
-mtime n: 最近一次文件内容修改日期距离今天的天数
-name pattern: 用不带路径的文件名匹配 pattern
-path pattern: 用带路径的文件名匹配 pattern
-perm mode: 权限位等于 mode
-size n[cwbkMG]: 文件大小
-type c: 文件类型
注意区分上述选项中的 amin, cmin, mmin。这组区别还在 stat filename 时出现,即对应”access”, “change”, “modify” 三个时间戳:
- 用 vim 编辑文件内容,三项都会更新
- 重命名文件,change 会更新
- 用 cat 列出文件内容,access 会更新
- 用 echo > file 的方式向文件追加内容,change 和 modify 会更新
总而言之,当调用 read 系统调用读取文件时,根据定义 access 会更新;调用 write 系统调用写入文件内容时,根据定义 modify 会更新,同时由于文件大小这一元信息改变,change 会更新;移动或重命名文件时,change 会更新。
find 中的行为
-delete 删除
-exec command; 执行命令
-printf format 按格式打印
find 举例
find root_path -type d -iname '*lib*'
列出所有文件夹名包含 lib(不区分大小写)的文件夹
find root_path -name '*.py' -not -path '*/site-packages/*'
列出所有 .py 文件,排除路径中有 site-packages 的文件
find root_path -maxdepth 1 -size +500k -size -10M
下降至多一层,找到所有大小在 500k~1M 之间的文件
find . -not -type d -exec wc -l {} \;
对所有文件数行数
Leave a Reply