将 grep 结果过滤为仅指向现有文件的路径

Filter grep results down to paths to existing files only

我正在使用 git diffgrep 来列出特定文件夹中在上次提交中更改的所有文件:

paths=$(git diff --name-only HEAD HEAD~1 | grep "desired_folder/")

现在我需要过滤列表,仅包含实际指向现有文件的字符串,并删除不指向现有文件的字符串。我该怎么做?

--diff-filter 标志对我没有用,因为我需要在一个分支上获取更改列表,然后仅过滤到存在于不同分支上的文件。

编辑 - 示例行为:
输入字符串:

"file1.txt file2.txt folder/file3.txt"

当前文件夹树:

|-- file1.txt
|-- folder/
    |-- file3.txt

预期输出:

# file2.txt got removed, because it does not represent 
# path to an existing file
"file1.txt folder/file3.txt"

如果您以 space( ) 分隔符字符串结束,我们可以遍历这些文件名,并检查它们是否存在。

#!/bin/bash
res=""
files="file1.txt file2.txt folder/file3.txt"
for path in ${files// / }; do
    if [ -f $path ]; then
        [ -z $res ] && res="$path" || res="${res} ${path}"
    fi
done
echo "$res"
file1.txt folder/file3.txt

Try it online!

警告:由于路径由 space 分隔,路径本身应该 而不是 包含 space.

您可以使用 while 循环遍历 git diff 的结果,语法有点奇怪,以避免必须创建子 shell:

while read; do
  :
done < <(cmd)

你的情况:

while IFS= read file
do
  [ -f "$file" ] || continue # skip non existing files
  echo "$file" # file exists and is a regular file
done < <(git diff --name-only HEAD HEAD~1)

您可以将 grep 放在 git diff 后面,请注意您需要保留在进程替换中:

< <(git diff ... | grep ...)

while 循环将从 git/grep 的输出中读取每一行并将该行存储在变量 file.

请注意 git diff --name-only 显示相对于 git 存储库根目录的文件,您可能需要添加 --relative 以使它们相对于当前工作目录。