0%

用到的shell

1. 终端命令行移动

  • 到行首

ctrl + a

  • 到行尾

ctrl + e

  • 往左删除到行首

ctrl + u

  • 往右删除到行尾

ctrl + k

  • 往左删除1个单词

ctrl + w

  • 往右删除1个字符

ctrl + d

  • 左移1个字符

ctrl + b

  • 右移1个字符

ctrl + f

2. 写脚本常用的

2.1. flock-执行脚本时,加一个文件锁,防止同时执行两次

1
2
#!/bin/bash
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
  • "$0": 当前执行的脚本文件名
  • exec: 执行一个新程序
  • env FLOCKER="$0": 设置环境变量
  • flock: -e 互斥锁, -n 非阻塞
  • 最后一个冒号':' : 也是bash内置命令,没用,相当于一个nop操作,方便一些时候重定向

如果环境变量中 "${FLOCKER}" != "$0" , 说明该脚本没有在运行,就启动运行: exec env FLOCKER="$0" flock -en "$0" "$0" "$@";

会设置环境变量,然后 flock 对脚本文件加锁, 然后再运行一遍该脚本 "$0" "$@", 这时候环境变量就有值了,会执行一个:(nop)继续运行;
如果 flock 加锁失败,因为是用 exec 直接起的程序,失败就直接退出了,不会再执行脚本

这段代码是 man flock 中的样板.

2.2. 查找最新的一个文件名

1
ll -rt | awk -F' ' '{print $9}' |tail -n 1

2.3. 查找某个程序的pid

1
2
3
4
5
function get_pid(){
ps -ef |grep -w "$1" |grep -v "grep\|gdb" |awk '{print $2}'
}

proc_pid=`get_pid nginx`

3. linux二进制发送

用nc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建命名管道
mkfifo foo

# 后台连接到服务器,从 foo 接收数据
nc 114.113.124.211 29006 <foo &
pid=$!

# 将 foo 用描述符 3 打开
exec 3> foo

# 发送二进制数据 23 23 07...
echo -e '\x23\x23\x07\xFE\x54\x45\x53\x54\x30\x37\x31\x37\x56\x45\x48\x30\x30\x30\x30\x30\x31\x00\x00\x29\x16\x06\x0D\x0F\x31\x0C\x00\x01\x34\x65\x63\x63\x34\x33\x32\x36\x66\x63\x66\x34\x7A\x7A\x79\x74\x31\x32\x33\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xBE' >&3

# 重工
echo -e '\x23\x23\x07\xFE\x54\x45\x53\x54\x30\x37\x31\x37\x56\x45\x48\x30\x30\x30\x30\x30\x31\x01\x00\x29\x16\x07\x19\x0E\x2F\x27\x00\xA4\x33\x39\x38\x38\x61\x61\x37\x32\x66\x36\x38\x62\x79\x74\x7A\x67\x31\x32\x33\x34\x35\x36\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x01\x25' >&3

# 关闭通道
exec 3>&-

# 关闭后台进程
kill $pid

4. 字符串转二进制再做base64

1
2
3
4
5
6
echo '35343633343335221008085013000400'| xxd -r -ps  | base64

# 解base64再打印十六进制字符串
echo NzE1NzA0NCIJJxBZRAAEAA== |base64 -d |xxd
# 或者
echo NzE1NzA0NCIJJxBZRAAEAA== |base64 -d |od -t x1 -Ano

5. 时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 输出 20211008145359
date +"%Y%m%d%H%M%S"

date +"%Y-%m-%d %H:%M:%S"

# 时间戳timestamp
date +%s

# 时间戳-->时间
date +"%Y-%m-%d %H:%M:%S" -d @1438617600

# 时间-->时间戳
date -d "2022-4-26 08:42:43" +%s

# 计算半小时(1800s)的时间,打印 2022-05-13 15:02:44.000
halfHour=$(date -d @$(expr $(date +'%s') - 1800) +"%Y-%m-%d %H:%M:%S.000")

# 5 分钟前的时间戳
date -d "5 minute ago" +"%Y-%m-%d %H:%M:%S"
date -d "2 hour ago" +"%Y-%m-%d %H:%M:%S"
date -d "3 day ago" +"%Y-%m-%d %H:%M:%S"

6. 计算校验码

1
echo -n "0F 80 00 67 01 51 36 18 97 37 00 00 " | xorcal

7. 十六进制转ascii,再base64

1
2
3
4
echo -n "23 23 02 fe" | hex2ascii | base64

# 解base64
echo -n "IyMC/kxaWVRCR0NXNE0xMDA0MTcwAQBMFQwfBRQmAQEDAQAAAA2/qxS+JzdkAQAl5AAAAgEBBDVOIE4gKxS+JxAFAActChkCtXhmBgE/DW4ByQ0TATRDASA+BwAAAAAAAAAAADY=" | base64 -d |catbin

8. tr 替换,删除

1
2
3
4
5
6
7
cat file | tr 'abc' 'xyz'
a->x
b->y
c->z

# 删除字符 a, b, c, 而不是字符串abc
cat file | tr -d 'abc'

9. zip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 压缩
zip -r ss.zip ss/

# 排除
zip -r ss.zip ss -x "path/to/dir1/*" "dir2/*"

# 不解压抽出一个文件,
unzip -o -j ss.zip conf/ss.cf -d /opt/
# -o 不提示,直接覆盖
# -j 不创建解压文件中的路径conf/, 直接将 ss.cf 放到 /opt/ss.cf中

# 解压到指定目录
unzip ss.zip -d /opt/
# -n 不覆盖已有的文件
# -o 不提示,直接覆盖

10. 读取输入

1
2
read -p "nihao:" name
echo ${name}

11. 文件前后缀

1
2
3
4
5
filename=ss.tar.gz
echo "${filename%%.*}" # ss
echo "${filename%.*}" # ss.tar
echo "${filename#*.}" # tar.gz
echo "${filename##*.}" # gz

12. switch case 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
case ${arg} in
"red")
;;
"blue")
;;
*)
;;
esac

case ${arg} in
"red"|"blue")
;;
"blue")
;;
*)
;;
esac

13. if 语句

1
2
3
4
5
6
if []
then
elif []
then
else
fi

14. 判断

存在 filename 打印 exists,不存在打印 not exists

1
[ -e filename ] && echo "exists" || echo "not exists"

14.1. test condition:

1
2
[ ]: 跟test一样的,只能用 -a, -o, 是bash 命令
[[ ]]: 支持正则,支持 &&, ||, 是bash 关键字,常用这个

14.2. 判断文件

  • -b: 存在 && 块设备
  • -c: 存在 && 字符设备
  • -d: 存在 && 目录
  • -e: 存在
  • -f: 存在 && 普通文件
  • -L: 存在 && 符号连接
  • -p: 存在 && 管道
  • -s: 存在 && 非空
  • -S: 存在 && 套接字文件

14.3. 判断文件权限

  • -r: 存在 && 可读
  • -w: 存在 && 可写
  • -x: 存在 && 可执行
  • -u: 存在 && 该文件有 SUID 权限
  • -g: 存在 && 该文件有 SGID 权限
  • -k: 存在 && 该文件有 SBIT 权限

14.4. 两个文件对比

  • f1 -nt f2: f1 比 f2 的修改时间新
  • f1 -ot f2: f1 比 f2 的修改时间早
  • f1 -ef f2: f1 和 f2 的 inode 是否一样,针对硬链接判断两个文件是否一样

14.5. 整数判断

  • -eq: ==
  • -ne: !=
  • -gt: >
  • -lt: <
  • -ge: >=
  • -le: <=

14.6. 字符串判断

  • -z: 为空
  • -n: 不为空
  • ==: 相等
  • !=: 不等

14.7. 多个条件

  • -a: and
  • -o: or
  • !: not

15. 查看二进制文件

1
od -t x1 file

-A n: 不需要行号

16. 数学计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let a=10-1

val=`expr $a + $b`
val=`expr $a - $b`
val=`expr $a \* $b`
val=`expr $b / $a`
val=`expr $b % $a`

c=$[a+b]
d=$[a-b]
e=$[a*b]
f=$[a/b]
g=$[a%b]

echo '45.36-22.33'|bc
let a++
let a--

17. 手动计算系统当前占用总RSS

1
ps aux |awk '{sum+=$6} END {print sum/1024}'

18. 查看线程数

18.1. 查看程序的线程数

top -H, 系统的线程数

18.2. 某个程序的线程

1
2
3
pstree -p pid |wc -l
cat /proc/pid/status | grep Threads
ll /proc/pid/task/ | wc -l
1
ps -eLl |grep pid

19. awk

1
2
3
# 语法形式
awk [opts] 'script' var=value file(s)
awk [opts] -f scriptfile var=value file(s)

awk '{pattern + action}' {filenames}

根据 pattern 查找一行中的内容,然后做 action

pattern:

  1. /正则表达式/
  2. 关系表达式: 使用运算符操作,进行字符串或数字的比较测试
  3. 模式匹配表达式: ~ 或 ~!
  4. BEGING语句块,pattern语句块,END语句块

action:

  1. 变量或数组赋值
  2. 输出命令
  3. 内置函数
  4. 控制流语句
  • awk 求和
    cat data | awk '{sum+=$1} END {print "sum = ", sum}'

  • awk 平均值
    cat data | awk '{sum+=$1} END {print "avg = ", sum/NR}'

  • awk 最大值
    cat data | awk 'BEGIN {max=0} {if ($1>max) max=$1 fi} END {print "max = ", max}'

  • awk 最小值
    cat data | awk 'BEGIN {min=199999} {if ($1 < min) min=$1 fi} END {print "min = ", min}'

  • awk 第2列不同值出现的次数
    awk '{sum[$2]+=1} END {for (i in sum) print i"\t"sum[i]}' test.txt

  • awk 判断 第一列大于1,输出该行
    awk '$1 > 1 {print $0}'

  • awk 进制转换

    1. 十六进制转十进制
      echo '12AF' |awk '{print strtonum("0x"$0)}'

    2. awk 十进制转十六进制
      echo '1234' | awk '{print("%x\n", $0)}'

    3. awk 八进制转十进制
      echo '012347' | awk '{print strtonum($0)}'

  • 数组
    awk -F ' ' '{a[$1]=$3; if (a[$1]>"202201011") a[$1]="202201011";} END {for (i in a){print i,a[i]}}}'

  • 多个分隔符
    awk -F '[ /:]'

  • 去重并保留原顺序

1
cat list.txt | awk '!x[$0]++' 

awk 表达式为true,执行后续语句,为false,跳过该行;

x[] 是个 map, 用当前行$0做key,如果之前没有该key, x[$0]查不到,返回false, !返回真, 打印该行,并++(相当于insert);
后续再来个key, 有该值,!返回假,跳过该行;

有个好处是,不用那么大的内存。

  • 每行分割成一个单独文件

demo.txt

1
2
3
sample_1 a b c
sample_2 a b c
sample_3 a b c
1
cat demo.txt | awk -F ' ' '{out=$1".txt"; print >(out); close(out)}'

会分成3个文件,每个文件一行:

1
2
3
sample_1.txt
sample_2.txt
sample_3.txt

20. sed 替换

  • 将所有aaa替换成bbb

sed -i "s/aaa/bbb/g" file

  • 替换行

sed -i '/匹配字符串/s/替换源字符串/替换目标字符串/g' filename

  • 删除匹配行

sed -i '/匹配字符串/d' filename

  • 替换换行符成空格

sed -i ':a;N;$!ba;s/\n/ /g' file

通过 :a创建一个标记
通过N追加当前行和下一行到模式区域
如果处于最后一行前,跳转到之前的标记处。 $!ba ($! 意思是不在最后一行做这操作 (最后一行就被当成最后的一行)).
最后置换操作把模式区域(就是整个文件)的每一个换行符换成一个空格。

  • 删除换行

sed -i ':a;N;$!ba;s/\n//g' file

  • 删除纯空行

sed '/^\s*$/d' file

  • 删除纯空行和由空格组成的空行

sed '/^[ ]*$/d' file

  • 打印过去8分钟数据
1
`sed -n "/`date -d "8 minute ago"  +"%Y-%m-%d %H:%M"`/,\$p" file |grep OutOfMemoryError  | wc -l`

放到脚本中:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

last_time=`date -d "1 hour ago" +"%Y-%m-%d %H:%M"`
# 防止首行日志时间太早,搜不到正常的日志
log_head_time=`head -n1 ss.log |cut -b 1-16`
if [ $last_time -lt $log_head_time ]
then
last_time=$log_head_time
fi
search_word="The driver has not received any packets from the server"
search_cnt=`sed -n "/${last_time}/,\\$p" /log/ss.log |grep "${search_word}" | wc -l`

21. 正则

  • 不以某些字符串开头

^(?!str)


22. 读文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while read ll
do
echo $ll
done < file

cat file |while read ll
do
echo $ll
done

for ll in `cat file`
do
echo $ll
done

23. 将16进制字符串转换成二进制文件

data.raw.txt中存放的是16进制字符串,
head data.raw.txt

1
2
3
3031636481860159070000000025013000000189b4c5aabe0140d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5
303163648186015a070000000025013000000189b4c5aad50140d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5
303163648186015b070000000025013000000189b4c5aae90140d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5555555555454575754d4d6d555d5d7d455d7d1d555d45553595b5b5b52d5d1d0d9c6c1c0cdcddad551d4d5535c58434f465b5e56d2d9d155d5d55756d4d7505d535d5853d2ded3dfd9dbd9d0dfd8d650535056d7d2d75d52515357d6ddded655ded95759595841405e57ddd8d2d6ddd8d652445ed75e434551534152dec7ddd7dfc3f7f0fdc8c5da57474e44584f744e525859dcc4dad0ddd2585857565f5f565652455f515951dec1c3f5cbd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5
1
for ll in `cat data.raw.txt` ; do echo -n $ll |  sed 's/\([0-9a-zA-Z]\{2\}\) */\\\\x\1/g' | xargs echo -ne >> a.log  ; done

转换成这样
od -t x1 a.log |head

1
2
3
4
5
6
7
8
9
10
0000000 30 31 63 64 81 86 01 59 07 00 00 00 00 25 01 30
0000020 00 00 01 89 b4 c5 aa be 01 40 d5 d5 d5 d5 d5 d5
0000040 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5
*
0000520 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 30 31 63 64 81 86
0000540 01 5a 07 00 00 00 00 25 01 30 00 00 01 89 b4 c5
0000560 aa d5 01 40 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5
0000600 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5
*
0001260 d5 d5 d5 d5 30 31 63 64 81 86 01 5b 07 00 00 00

24. 特殊参数

  • $#: 所有参数个数,不包括开头文件
  • $@: 所有参数

25. 解析命令行脚本参数

在创建shell脚本时,尽量保持选项与Linux通用的选项含义相同,Linux通用选项有:
-a 显示所有对象
-c 生产一个计数
-d 指定一个目录
-e 扩展一个对象
-f 指定读入数据的文件
-h 显示命令的帮助信息
-i 忽略文本大小写
-l 产生输出得长格式文本
-n 使用非交互模式
-o 指定将所有输出重定向到输出文件
-q 以安静模式运行
-r 递归的处理目录和文件
-s 以安静模式运行
-v 生成详细输出
-x 排除某个对象
-y 对所有问题回答yes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 1. 手工处理
#!/bin/bash
while [[ "$#" -gt 0 ]]; do
case $1 in
-t|--target) target="$2"; shift ;;
-u|--uglify) uglify=1 ;;
*) echo "Unknown parameter passed: $1"; exit 1 ;;
esac
shift
done

echo "Where to deploy: $target"
echo "Should uglify : $uglify"

# 2. getopts 不支持长选项, shell内置
#!/bin/bash
echo "$@"
while getopts ":a:bc:" opt; do #不打印错误信息, -a -c需要参数 -b 不需要传参
case $opt in
a)
echo "-a arg:$OPTARG index:$OPTIND" #$OPTIND指的下一个选项的index
;;
b)
echo "-b arg:$OPTARG index:$OPTIND"
;;
c)
echo "-c arg:$OPTARG index:$OPTIND"
;;
:)
echo "Option -$OPTARG requires an argument."
exit 1
;;
?) #当有不认识的选项的时候arg为?
echo "Invalid option: -$OPTARG index:$OPTIND"
;;

esac
done

# 3. getopt, 支持长选项, 独立程序
-a:使getopt长参数支持"-"符号打头,必须与-l同时使用
-l:后面接getopt支持长参数列表
-n program:如果getopt处理参数返回错误,会指出是谁处理的这个错误,这个在调用多个脚本时,很有用
-o:后面接短参数列表,这种用法与getopts类似
-u:不给参数列表加引号,默认是加引号的(不使用-u选项),例如在加引号的时候 –longoption “arg1 arg2” ,只会取到”arg1”,而不是完整的”arg1 arg2”

#!/bin/bash
# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: -n 'example.bash' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true ; do
case "$1" in
-a|--a-long) echo "Option a" ; shift ;;
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
-c|--c-long)
# c has an optional argument. As we are in quoted mode,
# an empty parameter will be generated if its optional
# argument is not found.
case "$2" in
"") echo "Option c, no argument"; shift 2 ;;
*) echo "Option c, argument \`$2'" ; shift 2 ;;
esac ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
echo "Remaining arguments:"
for arg do echo '--> '"\`$arg'" ; done

26. 获取当前外网网卡

1
ip a |grep  -i 'up' |grep -vi loopback | awk -F ':' '{print $2}' |grep -io '[^ ].*'

27. xargs 参数

如果xargs要将命令行参数传给多个命令,可以使用-I参数。

1
cat foo.txt | xargs -I file sh -c 'echo file; mkdir file'

28. grep

  • 集合差集, 不能有空行,否则空行会匹配所有
1
grep -F -v  -f  use.log  all.log  # 从all.log中去掉use.log中的数据
  • -F: 匹配行

  • -f: 从文件中获取要匹配的行

  • -v: 反选

  • 贪婪模式有:

1
2
3
4
5
{m,n}
{m,}
?
*
+
  • 非贪婪模式有:
1
2
3
4
5
{m,n}?
{m,}?
??
*?
+?

centos上需要用 grep -oP 才生效.

29. for循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for ((i=1;i<=10;i++))
do
echo $(expr $i \* 3 + 1);
done


for i in $(seq 1 10)
do
echo $(expr $i \* 3 + 1);
done

for i in {1..10}
do
echo $(expr $i \* 3 + 1);
done

30. find

按时间查找:

  • -atime: 访问时间(读取),
  • -mtime: 修改内容了(写入),
  • -ctime: 元数据发生了变化(写入,文件属性,属主)

24小时内为第0天,当前时间 2022-4-24 16:04:22, 则第0天为 2022-4-23 16:04:22 ~ 2022-4-24 16:04:22

  • +1: 1天前,1x24小时之前的, ~ 2022-4-22 16:04:22
  • 3 : 第2天
  • -3: 3天内

删除1天前的文件:

1
find . -mtime +1 -delete

查找大小为0的文件:

1
find . -type f -size 0c
  • -type f: 常规文件
  • -size 0c: c表示 bytes, 默认是 b,表示 512bytes的个数

对找到的文件进行操作:

1
find . -type f -exec ls -l {}

查找多个类型文件:

1
find . -name "*.cpp" -o -name "*.h"

31. rysnc同步

rsync 默认使用文件大小和修改时间决定文件是否需要更新。

  • -a: 递归同步子目录,同步元信息(修改时间、权限等),同步软链接
  • -P: 等于 --progress --partial, 显示进度,从中断的地方恢复
  • --partial参数允许恢复中断的传输。不使用该参数时,rsync会删除传输到一半被打断的文件;使用该参数后,传输到一半的文件也会同步到目标目录,下次同步时再恢复中断的传输。一般需要与--append--append-verify配合使用。
  • --size-only参数表示只同步大小有变化的文件,不考虑文件修改时间的差异
  • -u、--update参数表示同步时跳过目标目录中修改时间更新的文件,即不同步这些有更新的时间戳的文件。
  • -v参数表示输出细节。-vv表示输出更详细的信息,-vvv表示输出最详细的信息。
  • -n参数或--dry-run参数模拟将要执行的操作,而并不真的执行。配合-v参数使用,可以看到哪些内容会被同步过去。
  • -c、--checksum参数改变rsync的校验方式。默认情况下,rsync 只检查文件的大小和最后修改日期是否发生变化,如果发生变化,就重新传输;使用这个参数以后,则通过判断文件内容的校验和,决定是否重新传输。
  • --delete参数删除只存在于目标目录、不存在于源目标的文件,即保证目标目录是源目标的镜像。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 排除1种文件
rsync -avP --exclude *.pth username@xxx.xxx.xxx.xxx:/home/username/your_dirpath/ /home/your_localdir/

# 排除多种文件1, 多个 --exclude
rsync -avP --exclude *.pth --exclude *.pkl username@xxx.xxx.xxx.xxx:/home/username/your_dirpath/ /home/your_localdir/
# 排除多种文件2, 用{}
rsync -avP --exclude={*.pth,*.pkl} username@xxx.xxx.xxx.xxx:/home/username/your_dirpath/ /home/your_localdir/

# 排除多种文件3, 用文件 --exclude-from
rsync -avP --exclude-from exclude_file.txt username@xxx.xxx.xxx.xxx:/home/username/your_dirpath/ /home/your_localdir/

exclude_file.txt中是这样:
*.pth
*.pkl

32. 十六进制转换

echo ‘0123456789’ |xxd -r -ps >> ss.bin

33. npm

  • 设置本地源
    npm config get registry
    npm config set registry http://10.8.7.101:7001/

  • 查看全局包安装路径
    npm root -g

  • 查看本地安装包
    npm list -g –depth 0

34. 数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 新建数组
arr=(A B C M1 M2 N)

# 读取单个
echo ${arr[0]}
# 读取所有
echo ${arr[*]}
echo ${arr[@]}
# 数组个数
echo ${#arr[*]}
echo ${#arr[@]}

# 追加
arr+=(D)

# 根据index删除单个
unset arr[1]
# 根据数值删除单个
arr=( ${arr[*]/C} )
# 根据包含的值删除几个
arr=( ${arr[*]/*M*} )

35. 获取脚本所在路径

1
2
3
4
5
6
# 正确实现
# 通过 readlink 获取绝对路径,再取出目录
work_path=$(dirname $(readlink -f $0))

# 或者曲线救国
work_path=$(cd "$(dirname "$0")";pwd)

36. 清空屏幕

清空当前屏幕: clear 或者快捷键 ctrl+l

但往上翻还会出现之前的历史,使用 reset 会连之前的历史也清掉,适合编译调试,tput reset 单纯reset会快一些,可以设置 alias rst="tput reset" 方便使用。

37. sort

只排序第1列,保持第2列的输入顺序

1
sort -s -k 1,1

38. 查看TCP网络状态

1
2
3
4
5
6
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

CLOSE_WAIT 6
ESTABLISHED 376
SYN_SENT 3
TIME_WAIT 59