【发布时间】:2010-11-19 18:42:48
【问题描述】:
我非常了解source(又名.)实用程序,该实用程序将从文件中获取内容并在当前shell中执行它们。
现在,我将一些文本转换为 shell 命令,然后运行它们,如下所示:
$ ls | sed ... | sh
ls 只是一个随机的例子,原文可以是任何东西。 sed 也是,只是一个转换文本的例子。有趣的是sh。我把我得到的任何东西都用管道传送到sh 并运行它。
我的问题是,这意味着启动一个新的子外壳。我宁愿让命令在我当前的 shell 中运行。就像我可以使用 source some-file 一样,如果我有文本文件中的命令。
我不想创建临时文件,因为感觉很脏。
或者,我想以与当前 shell 完全相同的特性启动子 shell。
更新
好的,使用反引号的解决方案当然有效,但我经常需要在检查和更改输出时执行此操作,所以我更喜欢最终是否有办法将结果传输到某些东西。
悲伤的更新
啊,/dev/stdin 看起来很漂亮,但是在更复杂的情况下,它不起作用。
所以,我有这个:
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin
这确保所有.doc 文件的扩展名都是小写的。
顺便说一句,可以使用xargs 处理,但这不是重点。
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv
所以,当我运行前者时,它会立即退出,没有任何反应。
【问题讨论】:
-
当您首先通过管道传输到临时文件然后对其进行源时,您的复杂命令是否有效?如果不是,生成的输出有什么问题?如果您的文件名中有空格或某些序列未正确转义,则命令的输出将不起作用。我想至少在 $1 和 $2.doc 周围添加引号。
-
有什么好的理由必须在原始 shell 中运行它吗? - 这些示例不会操纵当前的 shell,因此您这样做一无所获。快速的解决方案是将输出重定向到一个文件并获取该文件
-
@kaleb 输出运行良好。在这种特殊情况下,即使我通过管道连接到 sh。文件名是空间安全的,但感谢您的注意。 @nos 原始外壳上的 git 环境变量。再一次,这些只是例子。这个问题是终身的。
-
source /dev/stdin 在需要分配变量时对我不起作用。 freenode bash 上的 geirha 将我指向 mywiki.wooledge.org/BashFAQ/024 并建议我尝试一个对我有用的进程替换源