15

我网站的代码使用这段代码在服务器(Ubuntu)上自动部署。

cmd = 'cd ' + checkout_dir + ' && ' + svn_command + " st | awk '{print $2}' | grep -v ^deploy | tac | xargs -r" + svn_command + " revert -R && " + svn_command + ' up -r ' + options.revision

该命令的作用是cd进入结帐目录,运行svn status,然后提取文件名 ( $2),从列表中删除deploy目录及其所有文件(我不想恢复它)。如果没有参数它不会运行 svn revert 命令,否则它会运行。

不幸的是,xargs -r这在我的机器上不起作用(Mac OS X 10.8)。所以我被困在这里,有人可以帮忙吗?

4

4 回答 4

5

事实上,BSD 的实现xargs没有-r标志 ( --no-run-if-empty)。Linux 中的 GNU 版本有它。

这是一种在 Linux 和 BSD 中都可以使用的解决问题的方法:

... | (grep -v ^deploy || echo :) | xargs svn revert

如果的输出为空grep ... || echo :,中间的 将生成一个带有 a 的行。这有点,因为仍然会运行命令。如果您的存储库不包含该文件,那么这应该无效,因此可以接受。只要您的存储库中没有这样的文件,就可以是其他任何东西。:grepxargssvn revert :::

最后,正如@tripleee指出的那样,grep ... || echo :必须包含在 内(...),因为:

||优先级高于|,因此终止(第一个)管道。

您的代码看起来像一个 Python 字符串。这样会更易读:

kwargs = {
  'svn': svn_command,
  'dir': checkout_dir,
  'revno': options.revision,
}
cmd = "cd {dir} && {svn} st | awk -v r=1 '$2 ! ~ /deploy/ {{ print $2; r=0 }} END {{ r || print \":\" }}' | xargs {svn} revert && {svn} up -r {revno}".format(**kwargs)

我对你的原作做了一些改动:

  • 正如@tripleee建议的那样,移动了grep内部的逻辑。请注意,由于不再需要 hack,因此也不再需要包装awkgrep(...)
  • 放弃了tac,因为我看不出它的意义
  • 放弃了-Rfrom svn revert,因为我认为你不需要它
于 2013-07-01T19:02:22.590 回答
3

Not pretty, but hopefully a workaround.

cmd = 'cd ' + checkout_dir + ' && ' + 
    'r=$(' svn_command + ' st | ' +
        "awk '$2 !~ /^deploy/{print $2}' | tac) && " +
    'test "$r" && ' +
    svn_command + ' revert -R $r && ' +
    svn_command + ' up -r ' + options.revision

I'm not convinced that the tac is necessary or useful. I refactored the first grep into the Awk script for efficiency and aesthetic reasons.

To solve the general "my xargs lacks -r" problem, the gist of the solution is to convert

stuff | xargs -r cmd

into

var=$(stuff)
test "$var" && cmd $var

The unquoted $var will only work if it doesn't contain file names with spaces or other surprises; but then bare-bones xargs without the GNU extensions suffers from the same problem.

于 2014-06-08T10:06:12.790 回答
3

-rforxargs不适用于 OS X,因为它是 GNU 扩展。至于解决方法,您应该指定一些可以在xargs没有参数时解析或不调用命令的虚拟文件(之前可以检查)。

使用临时文件(或任何其他占位符)的方法:

some_cmd ... | xargs svn revert $(mktemp)

在 shell 中使用条件:

files=$(cd checkout_dir && ... | tac)
if [ -n "$files" ]; then
    echo $files | xargs && ...
fi

另请参阅:忽略 xargs 的空结果

于 2016-05-13T21:37:51.270 回答
1

xargs处理参数的 Bash 重新实现-r

#!/bin/bash
stdin=$(cat <&0)
if [[ $1 == "-r" ]] || [[ $1 == "--no-run-if-empty" ]]
then
    # shift the arguments to get rid of the "-r" that is not valid on OSX
    shift
    # wc -l return some whitespaces, let's get rid of them with tr
    linecount=$(echo $stdin | grep -v "^$" | wc -l | tr -d '[:space:]') 
    if [ "x$linecount" = "x0" ]
    then
      exit 0
    fi
fi

# grep returns an error code for no matching lines, so only activate error checks from here
set -e
set -o pipefail
echo $stdin | /usr/bin/xargs $@
于 2017-05-15T06:40:39.543 回答