UNIX系统把一切都看作文件,甚至命令终端也是和一个设备文件关联在一起的,可以通过向该文件写入来实现向终端写入信息,例如:
# 输出到当前终端
echo hoho > /dev/tty
# bash环境,发送到连接在ttys001端口的终端上
echo hoho > /dev/ttys001
dd
用来生成指定大小的文件,常用于硬盘读写测速
// 生成测试文件test.data
// 填充\0,大小为10M
dd if=/dev/zero of=test.data bs=1024 count=10k
// 写硬盘测速
// 对磁盘进行连续写入,不使用内存缓冲区,每次写入8k的数据,总共写入4k次,产生32M大小的文件
dd bs=8k count=4k if=/dev/zero of=test.data conv=fdatasync
// 读硬盘测速
dd if=test.data of=/dev/null bs=4k
if
是输入文件(input file),of
表示输出文件,bs
写入块的大小。/dev/zero
是特殊设备,用来产生无限多的\0
字符,dev/null
是空设备,输入的东西都丢掉
P.S.mac下conv
参数没有fdatasync
和fsync
选项
comm
comm
命令用来对比文本文件,实现diff。但输入必须是有序的文件,所以一般结合sort
使用:
# sort命令的-o选项表示输出到文件,这里直接替掉原文件
sort a.txt -o a.txt; sort b.txt -o b.txt
# 做diff
comm a.txt b.txt
P.S.wget
的-o-
选项长得很有意思,表示Get as a file and print the result on STDOUT
会得到3列结果,分别是:
# a有b没有的 b有a没有的 ab都有的
a差b b差a a交b
有这3列就能恢复a文件和b文件(有序的,排序之前的无法恢复),比如a=a差b并a交b
-1/-2/-3
选项删除指定的列,选项必须出现在输入文件前,例如:
# 去掉第三列,不输出a交b
comm -3 a.txt b.txt
# 把ab的差异合并到1列,结果是ab有差异的行
comm -3 a.txt b.txt | sed $'s/\t//g'
特别注意:正则表达式前面的$
取值运算,不加的话匹配不到制表符,与IFS=$'\n'
同理
P.S.Mac下sed -i
文件原地替换相当麻烦,必须指定备份文件名(虽然可以是空串)
diff
用来生成差异文件,例如:
# u选项输出更常见的格式,写入diff.txt
diff -u a.txt b.txt > ab.diff
按行比较文件,得出新增了哪些行,删除了哪些行(修改操作等价于新增新行删除旧行),结果类似于:
--- a.txt 2017-03-15 10:50:34.000000000 +0800
+++ b.txt 2017-03-19 16:56:14.000000000 +0800
@@ -1,6 +1,11 @@
+
+end yaya
data
-end
is
-line
no
+line
this
+
+newend
+line
用diff
结果给a和b打补丁就能得到b和a:
# 给a打补丁
patch -p1 a.txt < ab.diff
# ab的内容相同
md5 a.txt; md5 b.txt
要恢复原内容的话再patch
一次:
# 补丁回来
patch -p1 a.txt < ab.diff
也能对文件夹做diff
:
# N不存在的文件视为空文件,a所有文件视为文本文件,r递归比较子目录
diff -Naur data files
mkdir
用来创建文件夹,如果已经存在,就返回错误:
mkdir: bak: File exists
一般需要检查:
# 如果不存在的话,创建
if [ ! -e path ]; then mkdir $path; fi
对于深层路径,逐级检查比较费劲,可以简单丢弃错误:
mkdir ./dir1 2>/dev/null
mkdir ./dir1/dir2 2>/dev/null
mkdir ./dir1/dir2/dir3 2>/dev/null
更简单的做法是:
mkdir -p ./dir1/dir2/dir3
忽略已经存在的,创建需要创建的
文件权限
常见的3类权限:
user:文件的owner
group:用户组
others:除user和group用户外的用户
ls -l
列出的文件权限格式为:文件类型(1位)user权限(3位)group权限(3位)others权限(3位)
文件类型如下:
- 普通文件
d 目录
c 字符设备
b 块设备
l 符号链接
s 套接字
p 管道
后面的3位权限每位取值有4种:-rwx
,分别表示无/读/写/执行
P.S.如果文件权限是----------
的话,表示除root
外的所有用户都没有权限处理该文件,无法读写执行
另外有3种特殊权限,会出现在x
的位置:
setuid:允许用户以owner权限来执行文件,比如
-rws------
setgid:允许用户以owner所在组权限来执行文件,比如
----rws---
sticky bit:粘滞位,只有创建该目录的用户才有权限删除下面的文件,其它用户即便有写权限也删不了,比如
-------rwt
注意:s
和t
都有大小写两种,区别是s
表示有x
权限,S
表示没有x
权限
修改权限
chmod
命令,例如:
# 设置权限
chmod u=rwx g=rwx o=rwx test.sh
# 添加user执行权限
chmod u+x test.sh
# 添加所有执行权限
chmod a+x test.sh
# 删除user权限
chmod u-x test.sh
也可以用数值来设置权限:
# 等价于u=rwx g=rwx o=rwx
chmod 777 test.sh
777
是3组rwx
二进制表示对应的十进制数,比如r--
为4(100
)
P.S.一般把这个叫八进制值(值为0到7都不超过8?),实际上二进制解释更合理
设置3个特殊权限也用chmod
:
# setuid, setgid, sticky bit
chmod u+s
chmod g+s
chmod o+t
用数值设置的话,在3种权限前添一组sst
,例如chmod 2777 test.sh
中的特殊权限是2(010
),也就是-s-
表示setgid
权限
修改所属权的命令是chown
:
# 设置属于user1用户,属于staff组
chown user1.staff test.sh
一般配合setuid
权限使用:
# root组root用户
chown root.root bomb.sh
# 如朕亲临
chown u+s bomb.sh
touch
touch
摸一摸,存在的话更新时间戳,不存在的话创建一个空文件:
# 存在的话,更新所有时间戳为当前时间
touch test.sh
# 存在的话,只更新访问时间
touch -a test.sh
# 存在的话,只更新修改时间
touch -m test.sh
head/tail
只查看文件内容的某一部分,例如:
# 看前10行
head test.sh
# 看前3行
head -n 3 test.sh
# 不看后10行
head -n -10 test.sh
# 看后10行
tail test.sh
# 看后3行
tail -n 3 test.sh
# 不看前90行(输出第91行到结束)
seq 100 | tail -n +91
P.S.Mac下-n
参数不能是负数,会报错head: illegal line count -- -10
ls只列出目录
有3种方法:
# d选项最简洁
ls -d */
# F添上类型标识,筛选/结尾的
ls -F | grep "/$"
# l选项结果以权限开头,权限以类型开头,筛选d开头的
ls -l | grep "^d" | awk '{print $9"/"}'
也可以用find
:
# 按文件类型查找
find . -type d -maxdepth 1 -mindepth 1 -print
注意depth
范围,只找下一级
路径切换
经常用cd -
(cd $OLDPWD
)返回上次工作路径,实际上还有更强大的:
# 与cd作用看似相同
pushd /tmp
# 查看历史路径栈(-v编号)
dirs -v
# 返回上一次工作路径
pushd
# 返回上上一次...
pushd +1
# 返回上上上一次...
pushd +2
pushd
用来切换工作路径,交换栈顶记录与指定记录,但历史栈长度不变,需要删除记录的话,用popd
:
# 返回上一次工作路径,并删除当前路径
popd
# 删除上上一次工作路径
popd +1
# 清空历史栈(只保留当前记录)
dirs -c
+N
、-N
表示方向,+N
从栈顶开始数0123...
,-N
从栈底开始数
P.S.注意og my zsh
某个版本+-
方向是反的,bash
正常
wc
统计行数、单词数、字符数,常用于简单的代码统计:
# 输出行数、单词数、字符数
wc test.sh
# 取行数
wc -l test.sh | awk '{print $1}'
# 取单词数
wc -w test.sh | awk '{print $1}'
# 取字符数
wc -c test.sh | awk '{print $1}'
P.S.数单词的功能很弱,空格隔开的字符串就算一个单词,也不区分标点符号