命令行技巧

fd – 更好的 find 命令(fd – A nicer find command)

fd(https://github.com/sharkdp/fd ) 是 find 命令的一个更现代的替换。

fd(https://github.com/sharkdp/fd ) is a modern and nicer replacement to the traditional find command.

对比一下 Some comparisons

查找名字含有某个字符的文件 Find a filename with certain string

OLD

-> % find . -name "*hello*"
./courses/hello_world.go
./courses/chapter_01/hello_world.go
./courses/chapter_01/hello_world
./examples/01_hello_world.go

NEW

-> % fd hello
courses/chapter_01/hello_world
courses/chapter_01/hello_world.go
courses/hello_world.go
examples/01_hello_world.go

使用正则表达式查找 Find files using regular expression

比如说查找符合 \d{2}_ti 模式的文件。find 使用的正则表达式非常古老,比如说在这里我们不能使用 \d,也不能使用 {x} 这种语法。因此我们需要对我们的正则表达式做一些改写。关于find支持的正则表达式这里就不展开了。

fd 默认就是使用的正则表达式作为模式,并且默认匹配的是文件名;而 find 默认匹配的是完整路径。另外

For example, let’s find a file whose name matches \d{2}_ti. find uses a very ancient form of regular expression. Neither can we use \d, nor can we use {x}. So we have to adjust our expression to these kind of limitations.

fd, by default, uses regular expression as patter, and matches filenames; on the other hand, find uses the -regex option to specify a regular expression, and it matches the whole path.

OLD

-> % find . -regex ".*[0-9][0-9]_ti.*"
./examples/33_tickers.go
./examples/48_time.go
./examples/28_timeouts.go
./examples/50_time_format.go
./examples/32_timers.go

NEW

-> % fd "\d{2}_ti"
examples/28_timeouts.go
examples/32_timers.go
examples/33_tickers.go
examples/48_time.go
examples/50_time_format.go

指定目录 Find in a specific directory

find 的语法是 find DIRECTORY OPTIONS;而 fd 的语法是 fd PATTERN [DIRECTORY]。注意其中目录是可选的。这点个人认为非常好,因为大多数情况下,我们是在当前目录查找,每次都要写 . 非常烦。

find follows the syntax find <directory> <options>; meanwhile, fd uses fd <pattern> [<directory>]. Note that the directory part is optional. AFAIK, this is very convenient. Most of the times, we are just trying to find something in the working directory, typing . each time is very annoying.

OLD

-> % find examples -name "*hello*"
examples/01_hello_world.go

NEW

-> % fd hello examples
examples/01_hello_world.go

直接执行命令 Execute the command without arguments

find 会打印帮助信息,而 fd 则会显示当前目录的所有文件。

find will print help message, fd will print all the files in current directory

OLD

-> % find
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]

NEW

-> % fd
courses
courses/chapter_01
courses/chapter_01/chapter_1.md
courses/chapter_01/chapter_1.pdf
courses/chapter_01/hello_world
courses/chapter_01/hello_world.go

按后缀名查找文件 Find files by extension

这是一个很常见的需求,find 中需要使用 -name "*.xxx" 来过滤,而 fd 直接提供了 -e 选项。

It’s a very common use case. With find, you have to use -name "*.xxx", while fd provides -e option directly.

OLD

-> % find . -name "*.md"
./courses/chapter_01/chapter_1.md
./courses/chapter_1.md

NEW

-> % fd -e md
courses/chapter_01/chapter_1.md
courses/chapter_1.md

查找中过滤掉 .gitignore 中的文件 Exclude files listed in .gitignore

find 并没有提供对 .gitingnore 文件的原生支持,更好的方法可能是使用 git ls-files。而作为一个现代工具,fd 则默认情况下就会过滤 gitignore 文件,更多情况请查阅文档。

可以使用 -I 来包含这些文件,使用 -H 添加隐藏文件。

find does not natively support .gitignore files, a practical way would be using git ls-files. As a modern tool, fd ignores files listed in .gitignore and hidden files by default.

You could use -I to include those files, -H to also include hidden files.

OLD

-> % git ls-files | grep xxx

NEW

-> % fd xxx

排除某个文件夹 Exclude a directory

fd provides a -E option to exclude directories. You could put the directories in .fdignore, too.

OLD

-> % find . -path ./examples -prune -o -name "*.go"
./courses/hello_world.go
./courses/chapter_01/hello_world.go
./examples

NEW

-> % fd -E examples ".go$"
courses/chapter_01/hello_world.go
courses/hello_world.go

使用 xargs Using xargs

一般来说,如果使用管道过滤的话,需要使用 ‘\0’ 来作为字符串结尾,避免一些潜在的空格引起的问题。

find 中需要使用 -print0 来调整输出 ‘\0’ 结尾的字符串,在 xargs 中需要使用 -0 表示接收这种字符串。而在 fd 中,和 xargs 保持了一直,使用 -0 参数就可以了。

If you are using pipes to filter results, using \0 other than \n would be a better option to avoid some potential problems.

find with -print0 will output \0-terminated strings, and xargs‘s option is -0 to process them. fd chooses -0 as its option, which is consistent with xargs.

OLD

-> % find . -name "*.go" -print0 | xargs -0 wc -l
       7 ./courses/hello_world.go
       7 ./courses/chapter_01/hello_world.go
      50 ./examples/07_switch.go
...

NEW

-> % fd -0 -e go | xargs -0 wc -l
       7 courses/chapter_01/hello_world.go
       7 courses/hello_world.go
       7 examples/01_hello_world.go
...

总之,fd 命令相对于 find 来说相当简单易用了

As you can see, using fd can save you a lot of keystrokes.

PS

使用 exec Using exec

OLD

-> % find . -name "*.md" -exec wc -l {} \;
     114 ./courses/chapter_01/chapter_1.md
     114 ./courses/chapter_1.md

NEW

You could also omit the {}

-> % fd -e md --exec wc -l {}
     114 courses/chapter_1.md
     114 courses/chapter_01/chapter_1.md

Linux 命令行查看系统信息

查看机器名

uname -a # view system name
arch # show arch

查看 ubuntu 版本

show ubuntu version

cat /etc/*release

查看内存使用

free -mh

(master)kongyifei@localhost ~ $ free -mh
             total       used       free     shared    buffers     cached
Mem:          251G       241G       9.8G       5.9G       4.3G        76G
-/+ buffers/cache:       161G        90G
Swap:           0B         0B         0B

含义,第一行表示实际的内存占用情况,linux的机制是尽可能多的占用内存,所以free往往很小;但是占用的内存不一定都在被使用,也就是最后的buffers和cached内存是被系统预先占用的。
在第二行把这两项抛出,就是你的实际内存占用161G,实际可使用内存90G

iostat 和 vmstat

vmstat -awS M

(master)kongyifei.rocks@n8-147-097 ~/repos/crawl_deploy/svc_ctl $ vmstat -a
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
57  0      0 197155680 3614480 57558348    0    0     8    39    0    0  6  2 91  0  0

查看内存使用情况,其中最重要的是free和si、so三列,其中free表示空闲内存,si表示swap in,so表示 swap out

vmstat INTERVAL TIMES 执行vmstat每INTERVAL秒,并且执行TIMES次

http://www.orczhou.com/index.php/2010/03/iostat-detail/

命令行的一些小技巧

最近工作中经常用到的一些组合命令,本来想提交到 commandlinefu.com 上,但是忘记了密码,怎么也登录不上去了,记到这里吧

  • 脚本所在的目录
dirname $0
  • 文件夹下面按照占用空间大小排序
du -sh &#x60;ls&#x60; | sort -rh
  • 返回上一个目录
cd -
  • 显示所有的日志的最后几行
tail *
  • set
set -x # 显示每个执行的命令
set -e # 当有程序返回非0值时直接退出,相当于抛出异常
  • here doc
cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
        This line is indented.
EOF
  • 删除包含某个关键字的所有行
fd -t f -0 | xargs -0 sed -i /KeyWord/d
  • 在 shell 中,所有字符串都要用引号包围

Always quote strings in bash. If you string is empty and you are testing it with == or !=, then there will be a “== is not uniary operator” error

  • 替换一个文件夹下的所有文件
fd . -t file -0 | xargs -0 sed -i -e "s/make_redis_client/create_redis_client/g"

from: https://stackoverflow.com/questions/6758963/find-and-replace-with-sed-in-directory-and-sub-directories

Linux 内存与进程管理(ps/top/kill…)

ps 命令

比较有用的选项有

-e 显示所有的进程
-f 显示 uid, pid, ppid, cpu, starttime, tty, cpu usage, command
-j 显示 user, pid, ppid, pgid, sess, jobc, state, tt, time, command。个人更喜欢 -j 一点
-l 显示 uid, pid, ppid, flags, cpu, pri, nice, vsz=SZ, rss, wchan, state=S, paddr=ADDR, tty, time, and command=CMD.
-v 显示 pid, state, time, sl, re, pagein, vsz, rss, lim, tsiz, %cpu, %mem, and command

-L 显示能够排序的关键字(mac)
L 显示能排序的关键字(Linux)
-o/-O 指定显示的列,-o 只显示指定的列,-O有默认的几列,等价于:-o pid,format,state,tname,time,command

-S 把所有已经退出的进程的时间计算到父进程上(mac)
S 把所有已经退出的进程的时间计算到父进程上(Linux)
-u 按照 uid/username 过滤
-p/--pid 限制 pid
-g/--gid 限制 gid
-C 按照命令过滤
--ppid 按照 ppid 过滤
--ssid 按照 ssid 过滤
--tid 按照 tty 过滤

-E 显示环境变量
-H/--forest 按照进程树显示

--sort 按照某一列排序

-ww 不要限制显示的输出宽度

例子

  1. 使用ps显示占用内存最多的进程
% ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head
  1. 显示所有进程树
% ps -ejH

其他相关命令

pstree 查看进程树

pgrep process_name 按照名字查找进程 pid

top 命令

定时刷新系统的进程状态的监控程序。mac 上的默认排序是pid,Linux 上是 %CPU。mac 上的 top 程序和 Linux 上非常不一样。

  • top 教程:https://linoxide.com/linux-command/linux-top-command-examples-screenshots/
  • htop 教程:http://www.cnblogs.com/lizhenghn/p/3728610.html
  • atop 教程:http://www.cnblogs.com/bangerlee/archive/2011/12/23/2294090.html

atop

atop 用来分析机器在历史上的负载情况。通过 crontab 固定时间采样,组合起来形成一个 atop 日志文件,可以使用 atop -r XXX 对日志文件查看。

atop 每天以一个 /var/log/atop/atop_YYYYMMDD 的形式生成一个日志文件。

常用命令

  • b mm:ss 到指定时间
  • t 查看后十秒
  • T 查看前十秒
  • m 按照内存排序
  • C 按照CPU排序
  • c 查看详细命令

kill 命令系列

kill -s SIGNAL pid

或者 pkill xxx,不要使用 killall ,use pkill over killall

调整 nice 值

使用 nice 和 renice。nice 的范围是 -20 ~ 19,nice值越低,优先级越高。

nice -n 10 COMMAND # 以 10 为初始nice值启动命令
renice 10 -p pid

jobs 命令相关

jobs list all jobs

command & put job in the background

fg N to put it in the foreground

bg N to put it in the background

ctrl-z to put a job to sleep

kill %n to kill job number n

lsof

lsof -i:port 列出指定端口对应的进程

lsof -u username 指定用户

lsof -c process_name 指定进程名

lsof -p pid 指定pid

使用dmesg 查看当前的内核日志,debian上可以查看 /var/log/kern.log /var/log/dmesg.0

RSS is Resident Set Size (physically resident memory – this is currently occupying space in the machine’s physical memory), and VSZ is Virtual Memory Size (address space allocated – this has addresses allocated in the process’s memory map, but there isn’t necessarily any actual memory behind it all right now).[1]

[1] https://stackoverflow.com/questions/7880784/what-is-rss-and-vsz-in-linux-memory-management

shell 编程教程

变量和值

variables are referenced by $var or ${var}. Global variables are visible to all sub bash sessions, and are often called env variables, local variables are only visible to local session, not subsessions.

Global variables can be viewed as env, and can be created by export.

TEST=testing; export $TEST # or
export TEST=testing # NOTE: no $

Useful variables

HOME    Same to ~
IFS 
PATH    Search path
EUID    User id
GROUPS  Groups for current user
HOSTNAME    Hostname
LANG    
LC_ALL  
OLDPWD  
PWD 

定义和使用变量

定义变量,注意因为 shell 中的语法使用空格作为命令分割的限制,等于号前后不能加空格。

FOO=bar

使用变量,需要添加上 $ 符号。

echo $FOO

字符串在双引号中可以直接插入,这时候要加上大括号来指示变量名的起始位置。

echo "${FOO}xxx"

变量默认实在当前的回话中可见的,而不会作为环境变量传递给调用的命令。可以使用 export 导出变量,或者在命令前加上指定的环境变量。

-> % cat env.py
import os
print("FOO env variable is: ", os.environ.get("FOO"))

-> % python3 env.py
FOO env variable is:  None

-> % FOO=bar python3 env.py
FOO env variable is:  bar

使用 export

-> % export FOO=bar
-> % python3 env.py
FOO env variable is:  bar

一些有用的内置变量

$HOME     家目录,比如 /home/kongyifei
$IFS      默认的分隔符,和 for 循环紧密相关
$PATH     搜索路径,当你执行 ls 的时候,shell 会在这个变量中查找 ls 命令
$EUID     当前有效用户 ID
$LANG     
$LC_ALL   
$OLDPWD   上一个工作目录
$PWD      当前工作目录

数组

使用小括号来定义一个数组,关于 for 循环随后会讲

A=(1 2 3)

for el in ${A[@]}; do
    echo $el
done

字符串操作

大括号里面的字符串会被展开成独立的字符串

% echo {1,2,3,4}
1 2 3 4
% mkdir -p test/{a,b,c,d}{1,2,3,4}
% ls test/
a1  a2  a3  a4  b1  b2  b3  b4  c1  c2  c3  c4  d1  d2  d3  d4
% mv test/{a,c}.conf  # 这个命令的意思是:mv test/a.conf test/c.conf

切片: ${string:start:length}

默认值 ${var:-default}

设定值 ${var:=default}

长度 ${#var}

字符串 Expansion and slice

[zorro@zorrozou-pc0 bash]$ mkdir -p test/zorro/{a,b,c,d}{1,2,3,4}
[zorro@zorrozou-pc0 bash]$ ls test/zorro/
a1  a2  a3  a4  b1  b2  b3  b4  c1  c2  c3  c4  d1  d2  d3  d4

[zorro@zorrozou-pc0 bash]$ mv test/{a,c}.conf
这个命令的意思是:mv test/a.conf test/c.conf

${string:start :length} string slice

default value: ${var:-default}
set value: ${var:=default}

${#var} get variable length

Redirection

input: <, output >, append >>

cat > file << EOF
this
line
will
be redirected to
file
EOF

pipe

pipe commands will be run simultaneously, but the second command will wait for the input

Sub shell

use $(expression)

控制语句

条件语句

if 语句成立的条件是 expr 返回值为 0。

if expr; then
    statement;
elif expr; then
    statement;
else
    statement;
fi

test command

虽然可以使用任意的语句作为判断条件,不过我们一般情况下都是用 [ 这个命令来作为判断条件的,需要注意的是 [ 并不是一个语法,而是一个命令。不过由于 [ 这个上古命令实在功能太少,现在一般采用 [[ 来作为判断条件。

if [[ "a" == "b" ]]; then
    echo "wtf"
else
    echo "meh"
fi

[[支持的条件有

1 数值比较, 仅限整数,注意不能使用 > < 等符号。

n1 -eq n2   equal
n1 -ge n2   greater or equal
n1 -gt n2   greater
n1 -le n2       less or equal
n1 -lt n2   less
n1 -ne n2   not equal

2 字符串比较

Note: Variables may contain space, so the best way to comparison is to add quotes: "$var1" = "$var2"

str1 == str2    equal
str1 != str2    not equal
str1 < str2 less
str1 > str2 greater
-z str  zero
-n str  not zero length

3 file comparison

-d  is directory?
-e  exist?
-f  is regular file?
-r  exist and readable?
-s  exist and has content
-w  exist and writable
-x  exist and executealbe
-O  exist and owned
-G  exist and in same group
file -nt file2  newer than
file1 -ot file2     older than

case

case var in
parttern | pattern2) commands;;
pattern3) commands2;
*) default commnads;;
esac

Loops

foreach 语句

for var in list; do
echo $var
done

其中 list 可以是一个数组,也可以是一个被 $IFS 分割的字符串。默认情况下,$IFS 是 ” \n\t”。其中包含了空格。

如果要覆盖 IFS,一般这样使用:

OLDIFS=$IFS
IFS=”\n” # new seperator

do things

IFS=$OLDIFS

while-loop

until/while expr; do
# commands
done

pipe

the result of a for loop is pipe-able to other command

for city in beijing shanghai; do
    echo $city is big
done > cities.txt
# will save the result in cities.txt

输入输出

命令行参数

parameters to a script can be obtained as $1, $2, $3…。 $0 is the script name, remember to check whether the parameter is empty. $# is the number of parameters(without script name).

$0  script name / function name
$1...$x command line arguments / parameters
$#  number of arguments(without $0)
$*  all parameters as a string
$@  all parameters as a string list

shift

processing parameters using shift,

while [ -n “$1” ]; do
case “$1” in
-a) echo “option -a” ;;
–) shift
break;;
*) echo “$1” is not a option ;;
esac
shift
done

read

read OPTIONS VARNAME read input to variables

  • read -p Prompt
  • read -t timeout
  • read -s hide input

we can use read to read file or stdin

redirection

2> redirect STDERR
m>&n redirect fd m to fd n’s associated file

Note: you have to use command >> command.log 2>&1 (put 2>&1 at the end), since this means redirect 2 to 1’s
in a scirpt
exec 2> filename # reopen stdout to filename

Signal

trap commnad signal is used to handle signals in shell

Functions

有两种定义函数的方式

function name {
    # function body
}

foo() {
    # function body
}

要调用上面这个函数,直接就输入

foo

就好了

return

shell functions behave like a small script, and it does NOT return a computed value…It retures a exit code, which is between 0 and 255. if no return is specified, the exit code of last command will be returned

You can read the return value by $? like any normal commands

the right way to to return a value from function, you will have to echo out the value, and put the function is subshell

function foo {
    # do some compute
    echo $result;
}

retval=$(foo)

Note: any thing that echos in the function body will be captured, so please keep that from happen

parameters

like a shell script, $0 holds the function name, $1 … $9 holds the parameters, $# is the num of parameters

local variables

use local to declare local variables

alias

alias new_name="command string"
$ \command  # bypass alias

debugging

DEBUG macro

multiprocess

PIDARRAY=()
for file in filelist; do
md5sum file &;
PID
ARRAY+=(“$!”)
done
wait ${PID_ARRAY[@]}

Linux 命令行网络相关命令学习

iptables

使用 iptables -A 添加路由规则,使用 iptables -D 删除路由规则

fuser

查看哪个程序占用了给定端口

fuser XXX/tcp  # see which program is using tcp port XXX
fuser XXX/upd  # see which program is using udp port XXX
fuser -k XXX/tcp  # kill the program, if you have right permissions

curl

wget 功能很有限,httpie 虽然比较人性化但是有很多 bug,还是 curl 比较好用。

curl -L/--follow http://example.com           follow redirect
curl -I/--head http://example.com             only headers 
curl -o/--output file http://example.com      http -d
curl -v/--verbose http://example.com    
curl --data "key=value" http://example.com  
curl --data-urlencode "key=
curl -X/--request GET/POST http://example.com   
curl -H/--header "Accept: utf-8"    
curl --referer http://x.com http://example.com
curl --user-agent 

curl –cookie

使用代理

curl -x <protocol>://<user>:<password>@<host>:<port> --proxy-anyauth <url>

cookies

cookies 功能主要通过两个选项实现 -b/--cookie-c/--cookie-jar. --cookie 用于发送请求时
携带 Cookies, --cookie-jar 会把返回的 Cookie 按照 cookie.txt 规范存储到给定的文件中。

curl -v --cookie "USER_TOKEN=Yes" http://127.0.0.1:5000/
curl -v --cookie example.txt http://example.com

需要注意的是,如果 --cookie 的参数中包含了 =, 他就会被当做一个键值对来处理,而且可以
使用多个 Cookie, 用分号分开即可:”key1=val1;key2=val2;…”. 否则的话,这个参数会被当做文
件名,会读取对应文件的 Cookie, 这个文件同样要遵守 cookie.txt 的协议。

查看网络情况

需要注意的是,在 Linux 上 netstat 已经废弃了,应该使用新的 ss 命令。不过在 macOS 等 Unix 系统中,还是只有 netstat

netstat -a  list all ports
netstat -at list all tcp ports
netstat -l  all listening ports

netstat -in 查看提供网络接口的信息

netstat -rn 显示路由表

ifconfig eth0 显示接口的状态

ifconfig -a 所有接口的状态

ip addr eth0 全新的命令

Mac

和 Linux 基本相同,但是缺少 ip 指令,需要安装 iproute2mac 包

traceroute

nslookup

host

wget –noproxy

mtr

bt download

sudo add-apt-repository ppa:t-tujikawa/ppa
sudo apt-get update
sudo apt-get install aria2

使用 rsync 同步

rsync -azP localdir remotedir

  • -a archive,表示归档
  • -n dry-run,只显示要执行的操作而不具体执行
  • -z compress,压缩
  • -P –progress + –partial,显示进度同时断点续传
  • --exclude=<dir> exclude directory from being rsynced

默认情况下,rsync 使用增量同步,而不会删除文件。使用 --delete 删除文件

参考资料

  1. https://curl.haxx.se/docs/http-cookies.html

m4 tool

m4 macro language http://mbreen.com/m4.html

comman line invoking

m4 -D

builtins

define(, )
undefine()
ifdef(, , )
ifelse(, , , )
eval()
len()
include()
syscmd()
`’are quotes

for comments

M4 rules
it reads in the macro’s arguments (if any)
it determines the expansion of the macro and inserts this expansion at the beginning of its input
m4 continues scanning the input, starting with the expansion

example:
define(definenum',define(num',99′)’)
num # -> num
definenum num # -> define(num',99′) num -> 99

Unless a nested macro is quoted, it is expanded immediately:

define(definenum', define(num’, `99′))
num # -> 99
definenum # ->

Linux 命令行文本处理(sed/awk/grep…)

sort

-d 按照字典排序(默认)
-n 按照数字大小排序
-f 忽略大小写
-g 按照浮点数排序
-M 按照 Jan Feb 等排序

-r 逆序
-k 指定第 k 列排序 -t 指定分隔符
-b 忽略行首空格字符
-m 把两个已经排序的文件合并

uniq 合并重复

uniq 命令假定文件是已经排序的,因此基本要接着 sort 使用

  • sort unsorted.txt | uniq 删除重复行
  • sort unsorted.txt | uniq -c 统计行数
  • sort unsorted.txt | uniq -d 只显示重复行 -u 只显示不重复行

tr 翻译指令

tr “source” “target” 如果目标字符串太短的化,使用最后一个字符填充
tr -d “source” remove
tr -s “source” squeeze extra characters, useful for piping to cut
-c 参数对第一个字符串的补集
可以使用区间 a-z 0-9 等
还可以使用字符类 [:class:]

  • alnum:字母和数字
  • alpha:字母
  • digit:数字
  • space:空白字符
  • lower:小写
  • upper:大写
  • cntrl:控制(非可打印)字符
  • print:可打印字符

cut 选取某一列 sort
有三种模式 -b 按字节 -c 按字符 -f 按域 -d 指定分隔符
选取的列可以使用:

  • i 第 i 行
  • a,b i 行和 j 行
  • a-b 第 i 到 j 行

–completment 选取补集
–output-delimiter 输出

wc

统计单词 -c 字符数 -w 单词数 -l 行数

nl

给每行添加行号 -ba 所有行

paste

按列合并文本

xargs

xargs reformat the data it received and give it to next command. xargs squish all parameters into one line

-d set delemeters
-t 回显命令
-I 执行指定的 Instruction,需要指定操作符
如 ls *.md | xargs -t -I “%” cp “%” markdown/
-n output with n args on one line

regular expression in shell

|Commands|BRE|ERE|PCRE|
|——–|—|—|—-|
|sed ||-E/-r||
|awk||
||
|grep||-E|-P|
|find||
| |

Sed

Basic format

sed options script file

by default, sed uses BRE, but you probably want sed -E to enable ERE, see http://liujiacai.net/blog/2014/12/07/regexp-favors/. basically, sed works line by line and do transformation

s for substitution

sed s/day/night/OPTION OLDFILE > NEWFILE

默认只替换第一处出现, /g 替换所有

/只是默认的分隔符, 可以任意使用, 推荐使用:

使用 & 作为匹配到的字符, 使用 \1 \2 来表示匹配到的分组, 这种表达方式倒是和 pcre有些类似

使用 -r(linux) 或者 -E(mac) 才能够使用扩展的posix正则, 一定要带上这两个

OPTION

处理命令行输入输出的时候可能经常需要trim, 尤其是字符串带了\n的情况

sed -n ‘s/PATTERN/&/p’ file

sed ‘/PATTERN/p’ file

Options

-i  inplace
-i.bak  inplace with backup
-E/-r   use ERE

script

sed command syntax: option/pattern/command parameters
pattern selects lines and do command with parameters on those lines

awk

basic usage

gawk options program varlist file

gawk, like sed, is also line-oriented

vaiables

$0 the whole line
$1…$n word in line
NR number of rows
NF number of fileds

awk program

awk ‘BEGIN{ } pattern { } END { }’ file
BEGIN in used for initilization, and END is used to print out the result, pattern {} is run against each line

awk ‘pattern’ file
print lines with the pattern

grep

grep pattern file1 file2...
grep pattern *
grep pattern -r <dir>

force grep to show file name:
grep pattern file /dev/null

options

-v invert search
-r/-R recursively
-c count matching lines
-o printing matched part in differnet lines
-b -o output offset
-n with line numbers
-i ignore case
-l list matched files
-f pattern from
–include include files for grep
-Z use \0 as delemeter
-q no output only return value
-A n lines after
-B n lines before
-C n lines combined

ag

按文件过滤,支持多种文件类型,可以用ag --list-file-types查看支持的类型

Linux 命令行文件管理

get current file path

#!/bin/bash 
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH=$(dirname "$SCRIPT")
echo $SCRIPTPATH

这些程序基本都有一个模式:如果不给定文件作为参数,那么就从stdin读取,从 stdout 输出,非常适合 pipe,而且一般可以接受多个文件作为参数,并把结果合并

ls

ls 的一个很好用的命令组合 ls -sail

stat 和 file

stat 读取一个文件的所有信息,file 猜测文件的类型

cat

cat > fiie1 从标准输入读取并插入到file1
cat -ns file -n命令表示加入行号,-s 表示压缩多个空行到一个

chattr

find

Syntax

find <dir> [!] <filter> <action>

Filters

-name   后面可以跟通配符
-wholename  
-regex  Match on a whole path -iregex 不区分大小写
-type   文件类型 f 文件 d 目录 l 链接
-atime/mtime/ctime  使用+-区分未来过去,可以使用的单位smhdw
-newer file     比
-size   后面跟大小可以使用ckMGTP
-user/-group/-nouser    用户
-perm   权限
-path   在整个路径中,使用通配符

Actions

执行的动作跟在-exec/-ok后面

find ... -exec command {} + .. # give all files combined to the command
find ... -exec command {} \; # give each file

Tips

如果打印出绝对路径,使用find $PWD …

find with xargs

find ... -print0 | xargs -0 ...

A numeric mode is from one to four octal digits (0-7), derived by adding up the bits with values 4, 2, and 1. Omitted digits are assumed to be leading zeros. The first digit selects the set user ID (4) and set group ID (2) and restricted deletion or sticky (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file’s group, with the same values; and the fourth for other users not in the file’s group, with the same values.

权限

Linux 文件的权限可以使用0-7的四个八进制数字代表, 由1/2/4三个数字相加而成. 省略的数字会被认为是按0打头的. 第一个数字设定了 set user ID(4), set group ID(2) 和 限制删除或者叫 sticky bit(1). 第二个数字设定了文件所有者的权限: read(4), write(2), execute(1). 第三个设定了文件所在组的权限