如何测试路径是否在文件中列出?

How to test if path is listed in a file?

对于 windows 脚本,我有几乎完全相同的问题 ,但现在我需要在 linux 中做同样的事情。

我有一个脚本可以递归地查找所有 .h 文件并检查同一目录中是否有同名的 .cpp 文件。到目前为止这是有效的,但现在我想使用一个 Exclude.txt 文件,其中包含应该排除的文件夹。我的问题是 $file 是完整路径,但在 Exclude.txt 中我只想列出相对于 $pwd 的路径。我该怎么做?

#!/bin/bash
for file in $(find ${PWD} -name '*.h'); do 
    fileWithoutPath=$(basename $file)
    fileWithoutExtension=${fileWithoutPath%.*}
    prefix="$(dirname $file)/"
    suffix=".cpp"
    cppFile=$prefix$fileWithoutExtension$suffix

    if ??? path is not listed in ./Exclude.txt  ???   <--- what to put here?
        if [ -f "$cppFile" ]
        then
            echo "FILE EXISTS"
        else 
            echo "FILE DOES NOT EXIST"
        fi
    fi      
done

举个例子:

script is in:         /u/workingDir/
Exclude has a line:   foo

那么 /u/workingDir/foo/ 中的所有文件都应该被忽略。

relPathToFile=${file#$PWD}      # remove $PWD from beginning
while read -r excludePath; do
    if [[ $relPathToFile == $excludePath/* ]]; then
        if [[ -f $cppFile ]]; then
            ...
    fi
 done < './Exclude.txt'

您可以使用 readlink -f $some_file_name 获取完整的文件名,然后您可以检查文件是否在列表中。

思路:去掉$PWD前缀,就可以grep得到文件中的结果

这将删除当前目录前缀 $filename:

stripped_file=${filename##$PWD/}

一个例子:

$ cd /tmp
$ echo $PWD
/tmp
$ filename='/tmp/foo.txt'
$ echo ${filename##$PWD/}
foo.txt

重复使用这个技巧来查看相对路径是否包含剥离的文件名:

if [ "$stripped_file_name" != "${stripped_file_name##$relative_path}" ]; then
   # hey, removing the relative path worked, so the file must be
   # on the relative path; go on.
fi

否则你可以 $PWD添加到相对路径以使其成为绝对路径,并查看它们是否是绝对文件路径的前缀。

您可以调用 perl one-liner 将 $prefix 的绝对路径转换为相对于 $PWD 的相对路径(我们称之为 $relPath):

echo "$prefix" #=> /u/workingDir/foo/bar/
relPath=$(perl -e 'use File::Spec; print File::Spec->abs2rel(@ARGV) . "\n"' $prefix $PWD)
echo "$relPath" #=> foo/bar (<-- This is what you'd put into Exclude.txt)

接下来,我们将使用 grep 检查 $relPath 是否列在 Exclude.txt 中。如果是,我们将忽略该目录,如果不是,那么我们将检查 $cppFile 是否存在:

if ! grep -xqF "$relPath" ./Exclude.txt; then
   # Check for file...
   if [ -f "$cppFile" ]
      ...
   fi
else
   echo "IGNORE $relPath"
fi