输入和输出
*
Linux将每个对象当做文件来处理
*
文件描述符标识每个文件对象,为非负整数,每个进程一次最多开9
个文件描述符
*
bash shell 保留前三个文件描述符 0, 1, 2
0 STDIN
标准输入
cat
只输入cat命令,则从STDIN
接受输入
cat < testfile
从testfile
接受输入
1 STDOUT
标准输出
*
标准输出在终端界面上就是终端显示器
ls -al badfile > error.txt
命令错误时,错误并未重定向到error.txt中,错误的消息会显示在终端界面
2 STDERR
标准错误
*
默认情况下,STDERR
和STDOUT
文件描述符指向同样的地方(终端显示)
*STDERR
并不会随着STDOUT
的重定向而发生改变
ls -al badfile 2> testfile
重定向错误消息时,该值必须紧紧放在重定向符号前,若正常输出,则显示在终端界面
ls -al testfile 1> out.txt 2> err.txt
正常输出重定向到out.txt,错误输出重定向到err.txt中
ls -al a.file b.file &> out.txt
将STDOUT
,STDERR
重定向到同一输出文件out.txt,在该文件中shell 自动赋予了错误消息更高的优先级(错误消息显示在前)
脚本中重定向输出
*
临时重定向输出
*
重定向到文件描述符时,必须在前面加一个&
echo "first line" >&2
echo "second line"
#通过STDERR文件描述符重定向错误消息
./a.sh 2>test.file
cat test.file
first line
*
永久重定向
exec
命令启动一个新shell将STDOUT文件描述符重定向到文件
# 一旦重定向STDOUT STDERR很难将它们重定向到原来的位置
exec 2>errfile
echo "haha" # 这一句仍显示在终端,单下面的所有echo都显示在errfile或者outfile
exec 1>outfile
echo "hello"
脚本中重定向输入
exec 0< testfile
while read line # read 的输入为 testfile
do
echo $line
done
创建自己的重定向
*
可以使用[3-8] 之间的文件描述符
exec 3> test3 # exec 3>> test3 不用创建新文件,将输出追加到现有文件中
echo "test3" >&3
*
临时重定向输出,然后恢复默认输出设置的常用方法
exec 3>&1
exec 1>test1.file
echo "hhh"
exec 1>&3
*
创建输入文件描述符
exec 6<&0
exec 0< testfile
while read line # read 的输入为 testfile
do
echo $line
done
exec 0<&6
read -p "please input: " filename # read 的输入为STDOUT
...
*
创建读写文件描述符
exec 3<> testfile
read line <&3
echo "new line" >&3
#可能会出问题,读写同一文件,文件指针会变,可能结果超出预期
*
关闭文件描述符
exec 3>$-
重定向到特殊符号$-
,关闭文件描述符
exec 3> testfile
echo "test line" >&3
exec 3>&- #关闭文件描述符
# 如果在关闭文件描述符后,打开同一输出文件,shell会用一个新的文件替换一有文件
# 如果有输出数据,则会覆盖已有数据
列出打开的文件描述符
lsof -a -p $$ -d 0,1,2
当前进程打开的文件描述符信息
-p
指定进程ID(PID)
-d
指定要显示的文件描述符编号
-a
对其他的两个选项的结果执行布尔AND运算
$$
进程当前的PID,特殊环境变量
*STDIN,STDOUT,STDERR
的文件类型是字符型
*3-8
的文件类型是REG类型
阻止命令输出
/dev/null
系统上的NULL
文件,重定向到该位置的任何数据都会被丢弃
ls -al badfile 2>/dev/null
将错误消息丢弃
cat /dev/null > testfile
快速清除testfile中的数据
创建临时文件
mktemp testing.XXXXXX
该命令会用不重复的6个随机字符替换XXXXXX
,保证创建的临时文件是唯一的
tempfile=$(mktemp test.XXXXXX)
exec 3> $tmpfile
echo "hhhh"
exec 3>&-
rm -f $tmpfile 2> /dev/null
mktemp -t test.XXXXXX
t选项强制系统在临时目录创建文件(/tmp
),返回全路径
mktemp -d testdir.XXXXXX
创建临时目录
记录消息
date | tee testfile
命令tee将从STDIN过来的数据同时发往两处,一处是STDOUT,一个是指定的 testfile 文件
date | tee -a testfile
追加数据用 -a
选项
一个栗子
shell脚本用命令行参数指定待读取的.csv文件,创建sql语句
#!/bin/bash
outfile="members.csv"
IFS.OLD=$IFS
IFS=','
while read lname fname address city state zip
do
cat >> $outfile << EOF # 理解下这句话
INSERT INTO members(lname, fname, address, city, state, zip) VALUES
('$lname', '$fname', '$address', '$city', '$state', '$zip')
EOF
done < ${1}
IFS=${IFS.OLD}