数据呈现

重定向

1.文件描述符

linux用文件描述符标识每个文件对象,实现IO处理(输入输出)

每个过程一次最多可以用9个文件描述符,其中0-2有特殊含义。

文件描述符   缩写             描述                 备注  

0                  STDIN         标准输入          默认标准输入是键盘

1                  STDOUT    标准输出          默认标准输出是显示器

2                  STDERR    错误输出         默认错误输出是显示器

1.输入输出重定向(命令行)

1)输入重定向,使用<号:将要输入的内容更改为指定文件

标准输入命令:cat、wc等

# cat 
hello world   #键盘输入
hello world   #打印输入

输入重定向:

#wc < filename

2 4  16

2)输出重定向:

可以将命令的执行结果重定向输出到某个文件(默认标准输出到显示器)

>  file1      #将命令执行的标准输出到file1,覆盖

>> file1    #将命令执行的标准输出追加到file1,追加

2>  file1   #将命令执行的标准错误输出到file1,覆盖

2>> file1   #将命令执行的标准错误输出追加到file1,追加

&> file1    #将命令执行的标准输出和错误输出都重定向到file1(默认标准错误消息会显示在文件开头)

1> file1 2> file2  #将命令执行的标准输出到file1,标准错误输出到file2

#ls -l  &> file1   #将ls -l命令的执行结果(标准错误、标准输出)均输出到file1中,而不在显示器中显示。

1.输入输出重定向(脚本文件中)

临时重定向

>&2   #命令的输出结果,重定向输出到文件描述符2(标准错误默认输出到显示器)

>&1  #命令的输出结果,重定向输出到文件描述符1(标准输出默认输出到显示器)

#cat test1

#!/bin/bash

echo "This is an error message" >&2

echo "This is a normal message"

#./test1

This is an error message

This is a normal message

#./test 1 2> error.file   #将脚本中的标准错误,输出到error.file

This is a normal message

#cat error.file

This is an error message

永久重定向

exec 1> file  #将STDOUT文件描述符重定向到file文件,影响后续脚本的输出

exec 2> file   #将STDERR文件描述符重定向到file文件,影响后续脚本的输出

exec 0< file  #从file文件中获取输入,而不是键盘

举例1:标准输出重定向到文件

#cat file1
#!/bin/bash
exec 1> stdout.file   #后需的标准输出,均输出重定向到stdout.file中
echo "stdout line1"
echo "stdout line2"
#./file1
#cat stdout.file
stdout line1
stdout line2

举例2:多个exec

#cat file1
#!/bin/bash
exec 2> stderr.file   #后续标准错误,重定向到stderr.file文件
echo "stdout line1"
echo "stdout line2"
exec 1> stdout.file  #后续标准输出,重定向到steout.file文件
echo "stdout line3"
echo "stderr line1" >&2   #重定向到STDERR(标准错误)
#./file1
stdout line1
stdout line2
#cat stdout.file
stdout line1
stdout line2
#cat stderr.file
stderr line1

举例3:从stdin.file文件获取输入

#cat stdin.file
stdin line1
stdin line2
#cat file1.sh
#!/bin/bash
exec 0< stdin.file
count=1
while read line    #从stdin.file读取数据,而不是键盘
do
   echo "Line#$count: $line"
   count= $[ $count + 1 ]
done
#./file1.sh
Line#1: stdin line1
Line#2: stdin line2

自定义重定向

文件描述符3-8,当作输入或输出重定向都行

exec 3> file  #创建文件描述符3,将后续重定向到文件描述符3的内容,输出到file

exec 3>&1    #创建文件描述符3,将后续重定向到文件描述符3的内容,重定向到文件描述符1

exec 3<&0   #创建文件描述符3,将标准输入到文件描述符0的内容,输入重定向到文件描述符3

exec 3< file  #创建文件描述符3,将file的内容,输入重定向到文件描述符3

exec 3<> file  #同时读取、写入file

举例1:自定义的文件描述符重定向到文件

#test.sh
#!/bin/bash exec 3> stdout.file echo "stdout line1" echo "stdout line2" >&3
echo "stdout line3"
#./test.sh
stdout line1
stdout line3
#cat stdout.file
stdout line2

举例2:自定义的文件描述符重定向到另一文件描述符

#test.sh
exec 3>&1
exec 1> stdout.file 
echo "stdout line1"
echo "stdout line2"
exec 1>&3  #重新定义文件描述符1到3,上面定义了3到1,所以后续会标准输出
echo "stdout line3"
#./test.sh
stdout line3
#cat stdout.file
stdout line1
stdout line2

举例3:自动以文件描述符(费解)

# cat testfile 
line1
line2
[root@localhost test]# cat test1
#!/bin/bash
exec 6<&0        #STDIN输入到文件描述符6中
exec 0< testfile  #将testfile输入到STDIN中
count=1
while read line
do 
  echo "Line $$count: $line"
  count=$[ $count +1 ]
done
exec 0<&6  #将文件符6输出到STDIN
[root@localhost test]# ./test1
Line 1: line1
Line 2: line2
创建读写文件描述符

用同一个文件描述符,从文件读取、写入数据,shell会维护一个指针,用来在文件的位置。

# cat testfile 
this is the first line.
this is the second line.
this is the third line.
# cat test1
#!/bin/bash
exec 3<> testfile  
read line <&3      #从testfile读入1行数据,指针在第2行开始位置
echo "Read: $line"  
echo "this is a test line" >&3 #往testfile输入1行数据,覆盖指针位置的任何数据。
[root@localhost test]# ./test1
Read: this is the first line.
[root@localhost test]# cat testfile 
this is the first line.
this is a test line   #覆盖了this is the second l ,留了一个尾巴ine.未覆盖。
ine. 
this is the third line.

总结:

文件描述符与&或>之间不能加空格

>&  #加了&表示重定向到文件描述符

>   #不加&表示重定向到文件

exec 文件描述符1>&文件描述符2   #打开文件描述符1,重定向到文件描述符2

exec 文件描述符1> file1  #打开文件描述符1,重定向到file1

exec 文件描述符>&-    #文件描述符重定向到横线,表示关闭文件描述符

#cat test.sh
exec 1> stdout.file
echo "stdout line1"
exec 1>&-   #由于关闭了1,所以后续给1的内容,无法标准输出到显示器,所以第4行报错
echo "stdout line2"
#./test.sh
./test.sh: line 4: echo: write error: Bad file descriptor
#cat stdout.file
stdout line1

列出系统打开的文件描述符

lsof   

    -p  指定进程ID,$$表示当前进程

    -d 指定要显示的文件描述符个数

lsof命令输出结果有9列信息,分别是:

COMMAND  运行的命令名

PID   进程ID

USER 进程属主

FD   文件描述符号及访问类型(r读,w写,u读写)

TYPE 文件的类型,CHR字符型,BLK块型,DIR目录,REG常规文件

DEVICE 设备号 主设备号,次设备号

SIZE 文件大小

NODE  文件节点号

NAME  文件名

示例:

#cat test1
#!/bin/bash
exec 3> stdout.file1
exec 6> stdout.file2
exec 7< stdin.file1
/usr/sbin/lsof -p $$ -d0.1.2.3.6.7   #显示当前进程的0.1.2.3.6.7文件描述符
#./test1
COMMAND  PID USER   FD   TYPE DEVICE     SIZE   NODE NAME
。。。。。。省略
test1   4212 root    0u   CHR  136,0               2 /dev/pts/0
test1   4212 root    1u   CHR  136,0               2 /dev/pts/0
test1   4212 root    2u   CHR  136,0               2 /dev/pts/0
test1   4212 root    3w   REG    8,2        0 102201 /root/test/testfile1  
test1   4212 root    6w   REG    8,2        0 102208 /root/test/testfile2
test1   4212 root    7r   REG    8,2       15 102207 /root/test/testfile   
test1   4212 root  255r   REG    8,2      102 102210 /root/test/test1 

阻止命令输出

/dev/null文件,文件黑洞,横为空

举例:将错误信息输出/dev/null

#ls -al badfile okfile 2> /dev/null  #显示器只会显示正确的信息

-rwxr--r-- 1 root root 102 Jun 18 09:44 okfile

举例:使文件内容为空

#cat /dev/null > testfile

创建临时文件

mktemp  [option] 文件名

   -t    指定在/tmp目录下创建,默认在当前目录下创建(普通用户只能在/tmp目录下创建)

   -d   创建目录,不加-d表示创建文件

文件名:模板名.XXXXXX    文件名末尾必须是.XXXXXX,6个X随机生成,以保证文件名唯一 

权限:不考虑umask,文件权限:属主rw,目录权限:属主rwx

创建临时文件

$cat test1.sh

#test.sh
#!bin/bash
tempfile=`mktemp -t  szbfile1.XXXXXX`
exec 7> $tempfile
echo "line1" >&7
echo "line2" >&7
exec 7>&-
echo "line3"
echo "this tempfile name is: $testfile"
#./test.sh
this tempfile name is:/tmp/szbfile1.wH4347
#cat /tmp/szbfile1.wH4347
line1
line2

创建临时目录

$mktemp -t -d szbdir1.XXXXXX

/tmp/szbdir1.SQ4367

记录消息 tee

tee命令将STDIN的数据发往2个目的地,一个是stdout,一个是另以文件名

tee  [option] filename

  -a  追加内容到filename,默认覆盖

#date | tee curr.data

Sat Jun 18 10:47:21 PDT 2016

#cat curr.data

Sat Jun 18 10:47:21 PDT 2016

111
原文地址:https://www.cnblogs.com/zmdsg/p/7102148.html