shell

189 阅读1分钟

Shell Commands

Some Basics

Bash Manual

空格 space 在 shell commands 中用于 sparate arguments,例如foo=bar, echo $foo, 但不可以foo = bar, 因为这样会被看做 call program foo with first argument '=' and second argument 'bar'.

echo Hello  # 字符串输出
echo "Hello World"  # 字符串用双引号包裹
echo Hello\ World  # 使用了 \ 来escape
echo $PATH  # 从这些 path 中搜索 commands
which echo  # 查看是哪个 echo 被使用
pwd  # print working directory
cd ..  # change directory (to parent directory)
cd -  # cd 到上一个路径(switch)
ls -al ..  # list (all and long formatted) contents of parent dir
mv hello.py foo.py  # move or rename
cp hello.py foo.py  # copy
rm foo.md  # remove
man ls  # manual pages for ls
touch 1.py  # create new empty file
touch -t YYYYMMDDHHMM.SS filename  # 改时间

# 重定向
echo hello > hello.txt  # > < 用于重定向
cat hello.txt
cat < hello.txt > hello2.txt  # 1 cat hello.txt 2 cat 的输出
cat < hello.txt >> hello2.txt  # >> 表示append,hello2.txt里会有两行hello

# piple
# left | right,左边的output是右边的input(不一定非是文本,image video也可以)
ls -l / | tail -n1  # 只显示1行
curl --head --silent baidu.com | grep -i content-length | cut --delimiter=' ' -f2
# 输出81 (Content-Length: 81)
echo 1060 | sudo tee brightness  # tee 写入文件并在terminal显示

也可以写一个“自己的command”

touch mcd.sh
# vim mcd.sh
mcd () {
    mkdir -p "$1"
    cd "$1"
}
# :wq
source mcd.sh  # 可以加入到.bashrc
mcd test  # shell里面就可以用mcd了

$ (dollar sign)

参考stackoverflow$0表示script name;$1 ~ $9 positional argument,如果多于10,那么 ${10}$@ 所有的positional arguments;$*也是所有的参数,但不太一样 $@ 和$*的区别,结论是被双引号引起来的时候,$*会将所有的参数作为一个整体, $@会将各个参数分开,也就是更适合用于for;$#是参数的数量;$? is the most recent foreground pipeline exit status;$! is the PID of the most recent background command。

quoting

bash quoting

echo "hello world"
echo hello\ world  # \移除后面一个字符的特殊含义
echo "#!/bin/sh"  # echo表现不正常
echo '#!/bin/sh'  # 单引号可以阻止所有interpretation,而双引号只能解决大部分
# 但也不是说应该处处使用单引号,比如
foo=bar
echo "hello $foo"  # output: hello bar
echo 'hello $foo'  # output: hello $foo

& | || [ > 2> >> <()

./server.sh &  # run in the background
ls | grep .sh  # pipe, 上一条输出喂给下一条
mkdir test && cd test  # and, first is true then second
cd test || mkdir test  # or, first is false then second
mkdir test1; mkdir test2  # do both whether first one is valid or not
cat < hello.txt > hello2.txt  # 1 cat hello.txt 2 cat 的输出
cat < hello.txt >> hello2.txt  # >> 表示append,hello2.txt里会有两行hello
cat <(ls) <(ls ..)  # 两个地方的ls显示,<()把ls放在temporal file里

globbing

# {} cartesian product
touch foo{,1,2} # zsh下tab变成 touch foo foo1 foo2
echo {a..e} # a b c d e
touch dir{1,2}/foo{1..4}

ls -l 解读

-rwxr-xr-x    1 xushenglee  staff    48B Jan 28 20:22 2.sh
-rwxr-xr-x    1 xushenglee  staff    76B Apr 25 17:21 3.sh
drwxr-xr-x    2 xushenglee  staff    64B Jan 25 18:48 My Docs

第一列10个字符,第一个字符 ( d 或 - ) 表示是dir还是file,其他的还有比如 l 表示symbolic link,剩下9个字符3个一组,表示permission。owner (read write execute), group (read write excute), everyone else (read, write execute)。

对于 file read write execute 就是字面上的意思,但对于 directory,read 表示是否可以看见dir里有什么,相当于 ls;write 表示 rename dir,create or remove file in it(有个坑的地方,如果有 file 的 w,但没有其 dir 的 w,那么可以清空 file,但是不能删除该文件,因为没有对 dir 的写权限);execute 表示是否可以进入(cd)该文件夹。

Different Shells

Shortcuts

!号的各种用法

crtl + l  # 相当于 clear

# !! 补全上一条命令
rm -rf somedir  # permission denied
sudo !!  # 回车或者空格
sudo rm -rf somedir  # 帮你补全好了

# !$ 补全上一条命令的最后一个参数
ls dir1 dir2
ls !$  #  => ls dir2
# 补全上一条命令的第一个参数
ls -al !^  => ls -al dir1
# 补全上一条命令的所有参数
ls !* => ls dir1 dir2

# {} cartesian product
touch foo{,1,2} # zsh下tab变成 touch foo foo1 foo2

sed command

cat Downloads/abc.txt | sed -nE 's/.*([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}).*/\1/p' | sort | sed -e 1b -e '$!d'