【问题标题】:Trying with piping commands into an if statement尝试将管道命令放入 if 语句中
【发布时间】:2015-12-18 02:24:15
【问题描述】:

我有一个 bash 脚本,它可以将一堆命令创建为一个文本文件。然后将cats 文件放入sh 以运行命令。我要做的只是在目录不存在的情况下运行命令。

这是我所拥有的:

一个类似这样的文本文件:

mkdir /path/to/a/directory
mkdir /path/to/another/directory
mkdir /path/to/yet/another/directory

在我的脚本中我有这样一行

cat /path/to/my/file.txt | sh

但是有没有办法做这样的事情?

cat /path/to/my/file.txt | if path already exists then go to the next, if not | sh

换句话说,如果路径已经存在,我想跳过创建目录的尝试。

【问题讨论】:

  • 无法将命令通过管道传输到if。你的项目听起来过于雄心勃勃。获得一个更简单的版本,并决定是否真的值得努力重建 shell 脚本范例;-)。 dir 存在的传统测试是if ! [[ -d "$dir" ]] ; then mkdir -p "$dir" ; fi。祝你好运。
  • 问题不在于你不能通过管道传递给if 语句(你可以),而是你真的需要一个循环。
  • @chepner :您可以通过管道传递到if 语句!?酷,你能在这里给出一个 1/2 衬里的例子作为评论吗?谢谢
  • 这并不像你想象的那么令人兴奋; if 不使用其打开的文件句柄,而只是将它们传递给其中包含的任何命令。 somecommand | if [ -f output.txt ]; then cat >> output.txt; else cat > output.txt; fi。在>> 不会创建文件的世界中,这个玩具示例会将命令的输出写入或附加到输出文件中。 cat 命令从 if 继承其标准输入。

标签: linux bash if-statement pipe sh


【解决方案1】:

更新:OP 已经澄清mkdir 的使用只是一个例子,他需要一个通用 机制来有条件地执行文本文件中的行包含 shell 命令,取决于命令是否引用现有目录:

while read -r cmd dir; do [[ -d $dir ]] || eval "$cmd $path"; done < /path/to/my/file.txt
  • while 循环逐行读取包含 shell 命令的文本文件。
  • read -r cmd dir 将每一行解析为第一个标记 - 假定为命令(示例输入中的 mkdir) - 其余部分假定为目录路径。
  • [[ -d $dir ]] 测试目录路径是否存在,|| 仅在测试失败时执行其 RHS,即如果目录不存在。
  • eval "$cmd $path" 然后执行该行;请注意,此处使用eval 的安全性不亚于通过管道传输到sh - 在这两种情况下,您都必须信任表示命令的字符串。 (在当前 Bash shell 中使用 eval 意味着 Bash 将执行命令,而不是 sh,但我假设这不是问题。)

原始答案,基于实际使用mkdir的假设:

在您的情况下,最简单的方法是将 -p 选项添加到您的 mkdir 调用中,这将悄悄地忽略创建已存在目录的尝试:

mkdir -p /path/to/a/directory
mkdir -p /path/to/another/directory
mkdir -p /path/to/yet/another/directory

换一种说法:mkdir -p 确保目标目录存在,无论该目录是否存在。已经存在或必须创建。 (mkdir -p 仍然可能失败,例如当目标路径是 文件 而不是目录时,或者如果您没有足够的权限来创建目录。)

然后您可以简单地将文件传递给sh(不需要cat 和效率较低的管道):

sh /path/to/my/file.txt    

如果您不控制输入文件的创建,您可以使用sed 插入-p 选项:

sed 's/^mkdir /&-p /' /path/to/my/file.txt | sh

【讨论】:

  • 非常感谢,很高兴知道这一点,但我实际上并没有使用 mkdir,我正在使用另一个基本上作为 mkdir 运行的脚本,但可以在我们的内部网络上运行。遗憾的是,该脚本没有 -p 标志,但这又是对未来有用的信息!
  • @VanCityGuy:很高兴您找到了解决方案,我的回答仍然有帮助。以后,请从一开始就说明所有限制条件,以及样本输入的哪些方面是偶然的。我在答案的顶部添加了一个通用解决方案,希望它也涵盖您的用例。
【解决方案2】:

我不清楚您是否要检查文件或目录是否存在.. 但这里是如何做到的:

如果文件存在则运行你的命令:

[ -f /path/to/my/file.txt ] && cat /path/to/my/file.txt | sh

或检查目录:

[ -d /path/to/my/directory ] && cat /path/to/my/file.txt | sh

【讨论】:

  • 这是最有帮助的。我实际上是这样使用它的:[ -d /path/to/dir ] || mkdir /path/to/dir 同样,如上所述,我实际上并没有使用 mkdir,但我能够合并这个答案,我使用 || 而不是 &amp;&amp;,因为我只希望它运行 if路径不存在。谢谢!
【解决方案3】:

编写您自己的mkdir 函数。

假设您的文件没有在任何应该工作的地方使用mkdir -p。

mkdir() {
    for dir; do
        [ -d "$dir" ] || mkdir "$dir"
    done
}
export -f mkdir

sh < file

【讨论】:

  • 感谢您的建议,但这有点超出我的想象。虽然看起来很有趣,但我必须对编写自己的函数进行一些研究,这对其他项目可能非常有用。谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 2016-05-27
  • 2021-06-21
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
相关资源
最近更新 更多