Should Know To Shell
学习资料:
The Missing Semester of Your CS Education
The Shell OverView
$ doller 符号,表示普通用户
# pound 符号,表示 root 用户
还需要知道的一点是输入流与输出流之间的隔离
$ # echo 500 > hello.txt // 因为前面有 # 符号,所以该语句整个都是由 root 权限运行的
$ sudo echo 500 > hello.txt
//因为一个是输入流(input of echo) 和这 输出流(output to hello.txt),这两个是隔离的,所以 sudo 程序运行了 echo and 500,但是shell 打开了 hello.txt,又因为此时 SHELL 是普通用户,所以后面的写入操作是普通权限写入
另外一种办法是利用 pipe promt
$ echo 500 | sudo tee hello.txt
当然还有一个方法
$ sudo su
#
The Shell Scripting
$ foo=bar // 定义了一个变量,注意没有空格
// 如果这样定义
$ foo = bar // 这意味着启动 fool 程序,携带第一参数 =,第二参数 bar
$ echo $foo //prints the conttent of foo variable
bar
// 这 single quote and double quote 的区别
$ echo "Hello $foo"
Hello bar
$ echo 'Hello $foo' // single qutoe 将不会 expaned string foo
Hello $foo
写一个脚本
$ vim mcd.sh
mcd() {
mkdir -p "$1" // 脚本中的 $0 - $9 指的是运行函数的时候,整个一行以 sapce 隔开的参数
cd "$1"
}
$ source mcd.sh
$ mcd test // 脚本运行时候,会把 $0 扩展成 mcd 程序, $1 扩展成 test
$? // 上一个命令的错误代码
$_ // 表示上一个指令的最后一个参数
!! // 敲下 enter 键,!!将会被替换成上一个命令,经常配合 Permision Denied 使用
< // 通过标准输入获取内容
> // 将东西放入标准输出
grep foobar mcd.sh // 从 .sh 脚本搜索 foobar
false ; echo "This is " // concatenate commands using a semicolon in hte same line
foo=$(pwd) // 得到 pwd 命令的输出-当前工作目录并将其存储在 foo 变量中
echo "We are in $(pwd)" // 因为是双引号,所以 thing will be expanded
cat <(ls) <(ls ..) // process substitution, 具体还是没理解,感觉像是 cat 执行了两遍 cat <(xx); cat <(xx)
sample example
echo "Starting program at $(date)" # 打印出现在的时间,同时可以指定不同的格式
echo "Running program $0 with $# arguments with pid $$" # $# 表示这个命令的参数数量,$$ 表示这个命令的进程 ID
for file in "$@"; do # 表示所有命令参数的集合
grep foobar "$file" > /dev/null 2> /dev/null #将 grep 命令的输出重定向到 dev/null,dev/null 就像是 unix 系统中的特殊设备,定位到此处表示 discarded。> 表示重定向标准输出 and 2> 表示重定向标准错误输出,因为流之间的分开的,所以需要告诉 bash 如何处理其中每一个流
if [[ "$?" -ne 0 ]]; then # #? 表示上面 grep 命令执行后的错误代码,-ne 是 not eaqul 好比其他语言中的 不等于, [[]] 好比 C 语言中的 ()
echo "File $file does not have any foobar, adding one"
echo "# foobar" >> "$file" # 追加 # foobar 字符串到 "$file" 文件中
fi
done
# for in ; do
# done
# if [[]]; then
# fi
$ ls
example.sh image.png mcd.sh project1 project42
$ ls *.sh # *表示任何内容 所以 *.sh 表示匹配以.sh结尾的名称的文件
example.sh mcd.sh
$ ls project? # ? 表示只匹配一个任意字符
project1
# 花括号 curly braces 是 combine command 一个普遍的使用方式
$ convert image.png image.jpg
$ convert image.{png.jpg} # 按下 tab 键 将扩展成上面的样子
$ touch foo{,1,2,10} # tab后 -> touch foo foo1 foo2 foo10
$ touch project{1,2}/src/test{1,2,3}.py //
$ touch project1/src/test1.py project1/src/test2.py project1/src/test3.py project2/src/test1.py project2/src/test2.py project2/src/test3.py
# 结合星号 asterisk and 花括号 curly braces
$ touch {foo,bar}/{a..j}
$ touch foo/a foo/b foo/c foo/d foo/e foo/f foo/g foo/h foo/i foo/j bar/a bar/b bar/c bar/d bar/e bar/f bar/g bar/h bar/i bar/j
$ diff <(ls foo) <(ls boo) # 比较两者输出的 difference
.py
#!/usr/bin/env python
# 上面别称作 magic line,当我们使用 ./xx.py ,shell 将会解释上面的指令,携带参数 "python" 调用 env command,效果就是将会从环境变量 python 的路径启动 python interpreter 去解释该脚本
import sys
for arg in reversed(sys.argv[1:]): #
print(arg)
shellcheck
Sometime maybe it's tricky to debug
这个命令将会检查 .sh 文件,给予 警告和 syntactic errors
$ shellcheck mcd.sh
tldr
convert + ffmpeg + tar
这是一个命令行程序,它的作用是提供一些关于该命令可解释的示例 explantory examples
$ brew install tldr# homebrew, mac 的包管理工具
$ tldr convert
convert # 处理图像的 command
ImageMagick image conversion tool.
More information: <https://imagemagick.org/script/convert.php>.
- Convert an image from JPG to PNG:
convert image.jpg image.png
- Scale an image 50% its original size:
convert image.png -resize 50% image2.png
- Scale an image keeping the original aspect ratio to a maximum dimension of 640x480:
convert image.png -resize 640x480 image2.png
- Horizontally append images:
convert image1.png image2.png image3.png +append image123.png
- Vertically append images:
convert image1.png image2.png image3.png -append image123.png
- Create a GIF from a series of images with 100ms delay between them:
convert image1.png image2.png image3.png -delay 10 animation.gif
- Create an image with nothing but a solid background:
convert -size 800x600 "xc:#ff0000" image.png
- Create a favicon from several images of different sizes:
convert image1.png image2.png image3.png image.ico
$ tldr ffmpeg
ffmpeg #处理 video
$ tldr tar
tar #解压缩文件/目录
find - fd alternative
$ find . -name src -type d # . 表示 current fold, -name 搜索的名称,-type 文件类型 ; 效果 recursively go throught the current folder 递归遍历当前的目录
$ find . -path '**/test/*.py' -type f # **表示当前所有路路径,该效果是每到一个文件夹寻找 test/*.py 文件
$ find . -mtime -1 # -mtime -1 表示 modified time 一天内被修改的文件
$ find . -name "*.tmp" -exec rm {} \; # 找到这些文件的路径,通过 rm 删除这些文件
locate
find 通过遍历目录结构来寻找某样目录或者文件
但是 locate 通过像数据库一样,建立索引结构,通过索引减少搜索时间和次数
$ locate docker
$ updatedb # 更数据索引结构 - 不是很清楚在什么时候使用
grep - fzf alternative
用来搜寻文件内容
$ grep foobar mcd.sh # 搜索 foobar 字符串,在 mcd.sh 文件中
$ grep -R foobar . # 递归搜索 foobar 字符串,在当前目录下
rg
rg 也是一个命令行搜索工具
目标是替代 grep
$ rg "import request" -t filetype ~/
$ rg "import request" -t filetype -C 5 ~/ # 展示围绕搜索的字符串上下 5行的内容
$ rg -u --files-without-match "^#\!" -t sh # u 是为了搜索范围包括这个隐藏文件, 搜索不匹配后面的正则表达式的文件
$ rg "import" -t go -C 5 --stats ~/Desktop # stats 输出额外的信息,例如行数、文件数量、打印的字符
/Users/lin/Desktop/client-go/listers/rbac/v1/role.go
16-
17-// Code generated by lister-gen. DO NOT EDIT.
18-
19-package v1
20-
21:import (
22- v1 "k8s.io/api/rbac/v1"
23- "k8s.io/apimachinery/pkg/api/errors"
24- "k8s.io/apimachinery/pkg/labels"
25- "k8s.io/client-go/tools/cache"
26-)
27404 matches
27139 matched lines
19319 files contained matches
23291 files searched
7472153 bytes printed
220173685 bytes searched
3.530092 seconds spent searching
1.788742 seconds
ag
ack 推荐-可以搜索文件内内容
brew install ack
两者都是类似的命令行 search tool
history
使用上下箭头是一种 print 我们使用过的命令的方式
但是 history 能检索更长时间段使用过的命令
$ history # 打印它所记录的所有历史命令
$ history 1 # 打印从第 1 行算起的所有历史命令
$ history | grep tar # 通过 pipe + grep 过滤命令
Ctrl+R
快捷键 Ctrl+R 向后搜索历史命令,这是大部分系统都拥有的功能
$ dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc
failing bck-i-search: conver_
fzf
模糊搜索工具fzf的安装和使用 --转载
Fuzzy finder(fzf+vim) 使用全指南 -- 转载
fuzzy matching 模糊搜索工具,我们可以搭配 cat 命令使用
这是一个很强大的工具,能配合很多工具使用
安装
$ brew install fzf
# 到对应的安装目录下执行 install 二进制文件
# yes 默认绑定快捷键后
$ source ~/.zshrc # 执行对应的 shell 配置文件
$ cat xxx | fzf
$ Ctrl+R 此时会非常好用了
切换当前工作目录
再比如进入到某个文件夹下面,使用 fzf 的过滤选择真是太方便了
cd $(find * -type d | fzf)
切换 git 分支
git checkout $(git branch -r | fzf)
fd
类比 find 的工具,也是用来搜索文件的工具
$ tldr fd
fd pattern
- Find files that begin with "foo":
fd '^foo'
- Find files with a specific extension:
fd --extension txt
- Find files in a specific directory:
fd pattern path/to/directory
- Include ignored and hidden files in the search:
fd --hidden --no-ignore pattern
- Execute a command on each search result returned:
fd pattern --exec command
broot
不是很懂这个工具,emmm