Fork me on GitHub

Linux笔记(4)

  在 Linux 中有3个常用的文件描述符,0(STDIN_FILNENO)代表标准输入,1(STDOUT_FILENO)代表标准输出,2(STDERR_FILENO)代表标准出错 ;一般每个进程最多允许同时打开1024个文件描述符,可用 ulimit -a 查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
core file size          (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 63928
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 63928
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

  在 C 语言中,stdin、stdout、stderr 也分别代表标准输入、标准输出、标准出错,不过 stdin 是 FILE类型,STDIN_FILENO 是 int 类型;使用stdin的函数主要有:fread、fwrite、fclose等,基本上都以f开头的 C语言库函数;使用STDIN_FILENO的函数有:read、write、close等,是 UNIX 类系统在<unistd.h>文件中定义的预编译宏。程序启动时:**FILE \ stdin / stdout / stderr 对应的 文件描述符(fd)分别是 STDIN_FILENO(0) /STDOUT_FILENO(1) / STDERR_FILENO(2)**。

  在 Linux 命令行上,经常会用到输入输出重定向:

1
2
3
4
5
标准输入stdin:对应的文件描述符是0,符号是<和<<,/dev/stdin -> /proc/self/fd/0

标准输出stdout:对应的文件描述符是1,符号是>和>>,/dev/stdout -> /proc/self/fd/1

标准错误stderr:对应的文件描述符是2,符号是2>和2>>,/dev/stderr -> /proc/self/fd/2

  输出重定向示例:

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
#默认情况下,stdin获取屏幕的输入(键盘),stdout和stderr默认输出到屏幕
#标准输出将ls的结果重定向到stdout文件中,错误输出默认到屏幕;1>与>等价
[deepcam@test ~]$ ls > stdout
[deepcam@test ~]$ cat stdout
Desktop
Documents
Downloads
examples.desktop
free.sh
Music
NVIDIA-Linux-x86_64-384.111.run
Pictures
Public
src
stdout
Templates
update
Videos
#标准输出将ls(gcc文件不存在,ls会出错)的结果重定向到stdout,错误输出到stderr,也可以使用追加>>模式。
[deepcam@test ~]$ ls gcc free.sh >stdout 2>stderr
[deepcam@test ~]$ cat stdout stderr
free.sh
ls: cannot access gcc: No such file or directory
#将错误输出关闭,输出到null;同样也可以将stdout重定向到null或关闭
# &1代表标准输出,&2代表标准错误,&-代表关闭与它绑定的描述符
[deepcam@test ~]$ ls gcc free.sh 2>&-
free.sh
#不关心错误输出,将其送到黑洞 /dev/null中
[deepcam@test ~]$ ls gcc free.sh 2>/dev/null
free.sh
#& 表示等同于的意思,2>&1,表示2的输出重定向等同于1,即和1重定向的文件系统上的位置是一样的
#&> 等同与 2>&1
#将错误输出和标注输出同时重定给/dev/null(不关心输出结果,常用在脚本中),也可以重定向到一个文件
[deepcam@test ~]$ ls gcc free.sh > /dev/null 2>&1
[deepcam@test ~]$ ls gcc free.sh &> /dev/null

  输入重定向示例:

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
#stdin获取屏幕的输入(键盘),然后输出到file文件,按Ctrl+d结束(表示文件结束的标志)
#> 写到文件回覆盖以前的内容,而 >> 会追加内容到文件
[deepcam@test ~]$ cat > file
this
is
a
file
[deepcam@test ~]$ cat file
this
is
a
file
#输入特定字符EOF,自动结束stdin,常用于向一个文件写内容
[deepcam@test ~]$ cat > test <<EOF
> this
> is
> a
> test
> EOF
[deepcam@test ~]$ cat test
this
is
a
test
#使用>> 追加
[deepcam@test ~]$ cat >> test <<EOF
> append
> hello
> world
> EOF
[deepcam@test ~]$ cat test
this
is
a
test
append
hello
world
#tac查看的内容和cat内容是倒过来的
[deepcam@test ~]$ tac test
world
hello
append
test
a
is
this
#rev是cat查看的内容反过来
[deepcam@test ~]$ rev test
siht
si
a
tset
dneppa
olleh
dlrow

  find的常见用法:

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
find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;
#path表示所查找的路径
#-option命令行选项
#-print将匹配的结果输出到标准输出,默认操作
#-exec command {} \;:find命令对匹配的文件执行该参数所给出的shell命令;注意{}和\;之间的空格。{}即为find查找的结果,\;表示转义;
#-ok:和-exec相同,只不过在操作前要询用户

#-option选项有很多,可以多个组合取交集,常见的有
-name 按文件名查找,支持正则表达式
-iname 同name,不区分大小写,不完全支持正则表达式
-type 根据文件类型查找:f、d、p、l、s、c、b
-empty 空文件或目录
-perm 根据权限查找文件
-user 根据文件所有者查找文件
-group 按组查找
-nouser 查找文件的用户ID不存在的文件
-mtime -n 按文件更改时间来查找文件,-n指n天以内,+n指n天以前
-atime -n 按文件访问时间来查
-ctime -n 按文件创建时间来查找文件
-size -n 根据大小查找文件,-n大小小于n,n大小等于n,+n大小大于n
-prune 忽略某个目录,多用于组合
#find . -name "[A-Z]*" -print 查以大写字母开头的文件
#find . -perm -777 -exec ls -l {} \; 查所有用户都可读写执行的文件
#find . -size +1000000c -print 查长度大于1Mb的文件
#find . -name .svn | xargs rm -rf 找到当前目录下所有名为.svn的文件并删除
#find ./ -empty -type f -print -delete 查找空文件并删除

  通常Linux命令可以用|首尾相连,上一个命令的 stdout 连接到下一个命令的 stdin标准输出作为后面命令的标准输入。但是如果命令不支持接收标准输入,那么就不能直接使用管道,比如lsrm等,是从命令行参数接受输入的。这时候如果想把上一个命令的输出传给它们,就不好办了。所以就有了xargs

  简单而言,xargs可以把从 stdin 接受到的输入,按空白符或加车符分隔开,然后依次作为参数去调用xargs后面的命令;xargs的默认命令是echo,空格是默认定界符。

1
2
3
4
5
#-d 		指定分隔符
#-n 传递参数的个数
#-p 询问是否执行,输入 y 继续执行,否则不执行
#-a file 从文件中读入作为sdtin
#-e flag 当xargs分析到含有flag这个标志的时候就停止

  在使用 find 配合 -exec 选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给 exec 执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现 溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。find命令把匹配到的文件 传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一 批,并如此继续下去。

1
2
3
4
5
6
7
8
#查找所有的jpg 文件,并且压缩它
# find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz
#用rm删除过多的文件,产生错误信息:/bin/rm Argument list too long. 用xargs去避免这个问题
#find ~ -name ‘*.log’ -print0 | xargs -i -0 rm -f {}
#ls *.txt | xargs -t -i mv {} {}.bak
mv 1.txt 1.txt.bak
mv 2.txt 2.txt.bak
mv 3.txt 3.txt.bak
------ 本文结束 ------