自用学术垃圾桶
用powerShell有些也行
在执行程序时在后面使用 -h
或 --help
标记看提示; 在前面使用man
查看手册;history
打印历史命令
date
打印日期、时间echo [参数1]
打印[参数1]; 注意shell中用空格分隔的被认为是不同参数, 例如echo [参数1] [参数2]
; 如果需要传递的参数包括空格, 用转义符号\
;
echo
实际上是一个程序,可以直接用路径替代echo
来执行$PATH
环境变量, 是用:
分隔的地址们which
确定程序名(e.g. echo
)代表的实际程序地址shell 中的路径是一组被分割的目录.
在linux中绝对路径由/
分割, 相对路径由\
分割.
linux中, 路径开头的/
代表的是系统的根目录,所有的文件夹都包括在这个路径之下, e.g. /bin/echo
.
Windows中路径用\
分割, 这是因为在Windows上每个盘都有一个根目录(例如:C:\
)
pwd
当前工作目录ls
list目录下的所有文件(默认当前目录); ls -l [目录]
;ls *.sh
globbing所有.sh
后缀名文件;ls [文件名]?
仅列举名字多一位的文件(?
占一位);ls [文件名]+tab+tab
可以筛选出包含这个名字的文件
文件的属性:
drwxr-xr-x
d
表示目录; 此后三位一读, 依次为文件所有者,用户组与所有人的权限;r = read, w = write, x = execute
powerShell中mode有d - Directory, a - Archive, r - Read-only, h - Hidden, s - System, l - Reparse point, symlink, etc
cat
读出文件内容mv
moverm [文件]
removecp [源] [末]
copymkdir
make directoryfind
递归查找文件
# 查找所有名称为src的文件夹
find . -name src -type d
# 查找所有文件夹路径中包含test的python文件
find . -path '*/test/*.py' -type f
# 查找前一天修改的所有文件
find . -mtime -1
# 查找所有大小在500k至10M的tar.gz文件
find . -size +500k -size -10M -name '*.tar.gz'
# 删除全部扩展名为.tmp 的文件
find . -name '*.tmp' -exec rm {} \;
# 查找全部的 PNG 文件并将其转换为 JPG
find . -name '*.png' -exec convert {} {}.jpg \;
grep
查找文件内容
grep "^\(gcc\|g++\)" # 只保留gcc或g++开头的行(正则表达式!)
默认的输入输出流是终端
[命令] < [输入地址]
[命令] > [输出地址]
最简单的重定向到文件(直接替换原有内容), e.g. cat < hello.txt > hello2.txt
[命令2] >> [输出地址]
(在原来的基础上)追加内容[程序1]|[程序2]|[程序3]
管道,像这样连接多个程序sudo
以superuser的身份执行
如果向/sys
下的系统文件写入,必须作为根用户
$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
#/sys/class/backlight/thinkpad_screen/brightness
$ cd /sys/class/backlight/thinkpad_screen
$ sudo echo 3 > brightness
#An error occurred while redirecting file 'brightness' open: Permission denied
$ echo 3 | sudo tee brightness
#correct 现在sudo是用于写入了
foo=bar
定义变量,注意没有空格(空格会被识别成参数)!echo "$foo"
或echo $foo
得打印变量中的内容(转义),echo '$foo'
打印原义字符串(无转义)foo=$(pwd)
命令替换(command substitution).这里pwd
命令的输出($(pwd)
)被写入foo
变量,通过STDIN传递返回值diff <(ls foo) <(ls bar)
进程替换(process substitution).<(ls foo)
将结果输出到一个临时文件,通过文件传递返回值mcd () { # make a directory and move to it
mkdir -p "$1"
cd "$1"
}
函数.source mcd.sh
加载并执行函数
$0
脚本名;$1
到$9
即其[参数1]至[参数9]$@
所有参数;$#
参数个数$?
前一个命令的返回值,e.g.执行完上一个命令后,echo $?
STDERR可以输出error code(0 fortrue
, 1 forfalse
)$$
当前脚本的进程识别码!!
完整的上一条命令,包括参数,e.g. 权限不足执行命令失败时,可以使用sudo !!
再尝试一次。$_
上一条命令的最后一个参数.如果你正在使用的是交互式 shell,你可以通过按下Esc
之后键入.
来获取这个值。
false || echo "Oops, fail"
true || echo "Will not be printed"
true && echo "Things went well"
false && echo "Will not be printed"
false ; echo "This will always run"
||
&&
代码按顺序从前往后执行,直至满足逻辑(如果第一个已经确定逻辑,之后的不会执行); ;
代码并列(均会)执行
grep
搜索字符串foobar
,如果没有找到,则将其作为注释追加到文件中。
#!/bin/bash
echo "Starting program at $(date)"
echo "Running program $0 with $# arguments with pid $$"
for file in "$@"; do
grep foobar "$file" > /dev/null 2> /dev/null
# 如果模式没有找到,则grep退出状态为 1
# STDOUT and STDERR redirected to NULL are discarded
if [[ $? -ne 0 ]]; then #-ne: not equal (\approx !=)
echo "File $file does not have any foobar, adding one"
echo "# foobar" >> "$file"
fi
done
?
和 *
来匹配一个或任意个字符,e.g. rm foo*
removes files that start with foo
.花括号{}
,自动展开一系列子串
convert image.{png,jpg}
# 会展开为
convert image.png image.jpg
cp /path/to/project/{foo,bar,baz}.sh /newpath
# 会展开为
cp /path/to/project/foo.sh /path/to/project/bar.sh /path/to/project/baz.sh /newpath
mv *{.py,.sh} folder
# 会移动所有 *.py 和 *.sh 文件
mkdir foo bar
# 排列组合,创建foo/a, foo/b, ... foo/h, bar/a, bar/b, ... bar/h这些文件
touch {foo,bar}/{a..h}
#!/usr/local/bin/python
或#!/usr/bin/env python
shebang行告诉内核在shell中也用python解释器.import sys
是与shell合调所需要的库
一些工具:shelldeck可以详细解释错误;tldr给出例程
^c
shell 会发送一个SIGINT信号到进程^\
发送SIGQUIT信号kill -TERM <PID>
发送更好用的SIGTERM信号^z
发送SIGTSTP信号(terminal stop)fg
前台继续bg
后台继续jobs
列出当前终端会话中尚未完成的全部任务.可以使用 pid 引用任务,使用百分号 + 任务编号选取任务,使用 $!
选择最近的一个任务nohup sleep 2000 &
防止SIGHUP终止后台(&后缀)进程;对已经运行的程序可以使用disown终端多路复用
Action | Keys combinations |
---|---|
start tmux | tmux |
quit(detach) a session | |
attach and detach session | tmux attach/detach, tmux attach/detach -t [name] |
list sessions | tmux ls |
create a session | tmux new -s [name] |
to travel among sessions | |
kill a session | tmux kill-session -t [name] |
Create window | |
Rename window | |
Switch to previous window | |
Switch to next window | |
Obtain navigable windows list | |
Kill a window | |
Split vertically | |
Split horizontally | |
visualise pane numbers | |
Move pane to the left | |
Move pane to the right | |
Switch panes layout | |
navigating | |
kill a pane |
在一切之前, SSH key配置: https://git-scm.com/downloads
git init
以创建子目录.git
,e.g.
git add *.c
git add LICENSE
git commit -m 'initial version'
git clone [网址] [自定义名]
.gitignore
文件中#
为注释,用globbing
# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
git status
,git status --short
或git status -s
给出更简洁add
->staged;staged:commit
->unmodified(up-to-date);rm
->untracked;
modified: stage
->staged;commit
->unmodifiedadd
后又修改了? 需要再add
后stage&commit
,不然保存的是老版本it commit -a
以跳过staged直接全部提交trackedgit rm -f
强制删除;git rm --cached [文件名]
仅停止跟踪不删除原文件;git rm [目录]/\*.[后缀名]
,git rm \*[名字结尾]
进行批量删除git mv file_from file_to
move可以用来重命名git diff
给出gnu diff format,对比当前文件与暂存快照的差异;git diff --stage
对比暂存文件与提交文件;git diff --cached
看已暂存的变化git log --author='author' --since=2.weeks
,git log --pretty=format:"%h %s" --graph
看提交历史 $ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
取消暂存,建议小心点用git reset HEAD [已暂存文件]
;撤销修改git checkout [修改后文件]
每一个type object = blob | tree | commit
,其中blob
保存文件快照,tree
记录目录,commit
包含一个指向上次提交对象(父对象)的指针.
Git 的分支本质上是指向提交对象的可变指针.默认分支master
指向最后一次提交,特殊指针HEAD
指向当前分支,分支独立不干扰,注意用git checkout [分支]
切换.
# 新建并切换分支
$ git checkout -b hotfix
# 将hotfix分支合并到master,指针右移(fast-forward)
# <--hotfix<--master
$ git checkout master
$ git merge hotfix
# 删除(抽离)hotfix
git branch -d hotfix
如果合并有文件冲突,可以用git status
看,用git mergetool
解决