Shell重定向¶
标准IO流¶
Shell 处理三个标准 I/O(输入/输出)流,每个都有一个文件描述符(FD):
- 标准输入(stdin):文件描述符 0(默认来自键盘)
- 标准输出(stdout):文件描述符 1(默认输出到终端)
- 标准错误(stderr):文件描述符 2(默认输出到终端)
覆盖重定向¶
我们可以通过>
操作符来把IO流输出到其他地方,这个操作就称为重定向(Redirection)。
例如,写一行代码到hello.py
,然后运行它:
$ echo "print('Hello World')" > hello.py
$ python hello.py
Hello World
默认情况下,我们使用>
重定向的是标准输出(stdout),如果要重定向标准错误需要使用文件描述符:
$ python -c "print(1" 2>error.log
$ cat error.log
File "<string>", line 1
print(1
^
SyntaxError: '(' was never closed
当然也可以同时重定向:
$ python -c "print(1);print('2)" > out 2>&1
# 1、2(stdout, stderr)都重定向到out
python -c "print(1);print('2)" > out 2>&1
# 也可以简写为
python -c "print(1);print('2)" &> out
追加重定向¶
>
操作符会把流输出到指定的文件,这个输出是覆盖的。如果我们想在原来的文件末尾添加新的内容,可以使用>>
操作符。
$ echo "print('You')" >> hello.py
$ python hello.py
Hello World
You
输入重定向¶
我们也可以使用<
操作符把文件作为stdin:
$ wc -l < out.txt # 统计行数
23
还可以使用<<
输入多行文本:
$ python <<EOF
print(1)
print(2)
print("END")
EOF
1
2
END
管道¶
实际上管道也是一种重定向,它把上一个命令的 stdout 作为下一个命令的 stdin。
例如:
$ echo "print('Hello'*10)" | python
HelloHelloHelloHelloHelloHelloHelloHelloHelloHello
根据unix哲学,Linux世界的绝大部分东西都是纯文本。因此,在管道的加持下我们可以迅速实现一些炫酷的操作。
Unix philosophy
It was later summarized by Peter H. Salus in A Quarter-Century of Unix (1994):[1]
- Write programs that do one thing and do it well.
- Write programs to work together.
- Write programs to handle text streams, because that is a universal interface.
管道中经常用到下列文本处理命令(类似消费者):
sort
:排序uniq
:去重grep
:过滤wc
:字数统计head
:文本的头部tail
:文本的尾部fold
:限制文本宽度xargs
:construct argument list(s) and execute utilityawk
:pattern-directed scanning and processing language
以及下列文本产生命令(类似生产者):
ps
:进程列表ls
:当前目录文件列表find
:查找文件seq
:产生序列pwd
:当前目录echo
下面给出一些实际案例
文件大小排序¶
对当前目录的所有文件和文件夹进行大小降序排列:
$ du -sh * | sort -hr
1.2G docs
1.1G site
52K overrides
24K index.html
24K _ai_summary_cache_chatgpt.json
20K LICENSE
12K nav.yml
8.0K mkdocs.yml
4.0K requirements.txt
4.0K plugins_simplify.yml
4.0K plugins_full.yml
4.0K build
4.0K README.md
.md 字数统计¶
递归寻找当前目录下的.md
文件,并且统计文件中的字数。按照字数降序排列:
$ find . -iname '*.md' -print0 | xargs -0 wc -c | sort -n -r | head -10
1070731 total
48432 ./docs/SomeMath/real/problems/recall_high_school_math.md
32767 ./docs/Python/BasicSyntax/builtin_class.md
32441 ./docs/Python/BasicSyntax/builtin_keyword.md
29551 ./docs/Python/SeniorSyntax/OOP.md
25553 ./docs/Blog/2023/travel_to_japan.md
22002 ./docs/Python/SeniorSyntax/functional_programming.md
19711 ./docs/Note/jupyter/jupyter4.md
19418 ./docs/Note/mkdocs/practice.md
19020 ./docs/SomeMath/real/gamma_func.md
ASCII码表¶
输出ASCII码表
$ printf "$(printf '\\%03o ' $(seq 32 126))\n" | fold -w 20
! " # $ % & ' ( )
* + , - . / 0 1 2 3
4 5 6 7 8 9 : ; < =
> ? @ A B C D E F G
H I J K L M N O P Q
R S T U V W X Y Z [
\ ] ^ _ ` a b c d e
f g h i j k l m n o
p q r s t u v w x y
z { | } ~
99乘法表¶
输出99乘法表
$ seq 1 9 | awk '{for(j=1;j<=$1;j++) printf "%d×%d=%-2d ", j, $1, j*$1; print ""}'
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
1×4=4 2×4=8 3×4=12 4×4=16
1×5=5 2×5=10 3×5=15 4×5=20 5×5=25
1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36
1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49
1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64
1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
丢弃输出¶
如果不需要特定的流,可以把它重定向到/dev/null
进行丢弃。
$ python -m this > /dev/null
Last update: 2025-02-13 20:38:21
Created: 2025-01-11 20:28:10
Created: 2025-01-11 20:28:10