Bash Shell以输出为参数连接两个程序

如果想要接入管道的程序并不适用于管道,该怎么办?例如,你可以用 rm 命令删除文件,将待删除的文件指定为命令参数即可:

rm my.java your.c their.*

但是,rm 并不会从标准输入中读取参数,因此不能按以下方式这么做:

find . -name '*.c' | rm

rm 只能以命令行参数的形式获取文件名,那该如何将先前运行过的命令(如 echo 或 ls)的输出放入命令行呢?

解决方案

使用 bash 的命令替换特性:

rm $(find . -name '*.class')

也可以使用 xargs 命令。

讨论

出现在 $() 中的命令是在子 shell 中运行的。$() 会被替换成所包含命令的输出。换行符会将输出变成多个命令行参数,尽管这种行为往往很有用,但有时也会产生出人意料的结果。

早期的 shell 语法没有使用$(),而是将命令放进反引号。在语法上,$()优于老式的反引号,因为前者更利于嵌套,自然也更容易阅读。但你可能更多看到的是 “,尤其是在有点年代的 shell 脚本中,或是从早先的 Bourne shell/C shell 成长起来的人们那里。

在这个例子中,find 命令的输出(通常是一系列文件名)成了 rm 命令的参数。

做这种操作时要格外小心,因为 rm 可是不讲情面的。如果 find 找到的文件比预想的多,rm 也会将其一并删除,无可挽回。这可不是 Windows,你无法从回收站中恢复已删除文件。可以用 rm -i 降低风险,选项 -i 会提醒你确认每次删除。对于小批量文件来说,这么做没毛病,但如果文件数量众多,那整个过程可就冗长不堪了。

在 bash 中,更安全地使用该机制的一种方法是先运行其中的命令,看看结果是否符合预期,如果没问题,再将该命令放入 $()。例如:

$ find . -name '*.class'
First.class
Other.class
$ rm $(find . -name '*.class')
$

后文会介绍如何用 !! 来确保更加万无一失,而不是重新输入 find 命令。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!