在shell中使用grep -q one-liners

时间:2015-11-25 18:30:12

标签: bash shell grep

我编写了一个脚本来列出包含特定文件的repo中的提交。它工作得很好,但我不明白为什么我要写这个:

for c in $(git rev-list "$rev_list"); do
    git ls-tree --name-only -r "$c" | grep -q "$file"
    if [ $? -eq 0 ]; then
        echo "Saw $file in $c"
    fi
done

而我通常会写同样的事情:

[[ $(git ls-tree --name-only -r "$c" | grep -q "$file") ]] && echo "Saw $file in $c"
# or
[[ ! $(git ls-tree --name-only -r "$c" | grep -q "$file") ]] || echo "Saw $file in $c"

两个短版本都不起作用:它们不输出任何内容。当我写它以显示所有不包含该文件的提交时,我得到输出:

[[ $(git ls-tree --name-only -r "$c" | grep -q "$file") ]] || echo "Did not see $file in $c"

但是,如果我从输出中获取提交哈希并运行

git ls-tree -r <the hash> | grep file

我注意到树中的文件 用于某些提交,这让我相信它只是列出了脚本处理的所有提交。无论哪种方式,我可能都错过了一些东西,但我无法弄清楚它是什么

2 个答案:

答案 0 :(得分:6)

您不需要在条件语句([[ $(command) ]])中包装该命令。实际上,这将无法与grep -q一起使用,因为您实际上正在测试命令是否打印。你可以这样做:

git ls-tree --name-only -r "$c" | grep -q "$file" && echo "Saw $file in $c"

一般来说,任何代码块都是

foreground_command
if [ $? -eq 0 ]
then
    bar
fi

可以替换为

if foreground_command
then
    bar
fi

甚至

foreground_command && bar

您应该使用的三种替代方案中的哪一种取决于foreground_commandbar或两者是否为多行命令。

答案 1 :(得分:0)

awk救援:

git ls-tree --name-only -r "$c" | awk "/$file/{printf '%s in %s\n', '$file', '$c'}"