遍历作为参数传递给 Bash 脚本的文件夹

Iterating through a folder that's passed in as a paramter to a Bash script

我正在尝试遍历一个文件夹,运行 对每个文件进行 grep,然后将它们放入单独的文件中,并用 .res 扩展名进行标记。这是我目前所拥有的....

#!/bin/bash
directory=$(pwd)
searchterms="searchterms.txt"
extension=".end"

usage() {
    echo "usage: fmat [[[-f file ] [-d directory ] [-e ext]] | [-h]]"
    echo "  file - text file containing a return-delimited list of materials"
    echo "  directory - directory to process"
    echo "  ext - file extension of files to process"
    echo ""
}

while [ "" != "" ]; do
    case  in
        -d | --directory )      shift
                                directory=
                                ;;
        -f | --file )           shift
                                searchterms=
                                ;;
        -e | --extension )      shift
                                extension=
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done

if [ ! -d "$directory" ]; then
   echo "Sorry, the directory '$directory' does not exist"
   exit 1
fi

if [ ! -f "$searchterms" ]; then
   echo "Sorry, the searchterms file '$searchterms' does not exist"
   exit 1
fi

echo "Searching '$directory' ..."
for file in "${directory}/*"; do
    printf "File: %s\n" ${file}
    [ -e "$file" ] || continue
    printf "%s\n" ${file}
    if [ ${file: -3} == ${extension} ]; then
        printf "%s will be processed\n" ${file}
        #
        # lots of processing here
        #
    fi
done

知道这是因为我对 globbing 的理解很差...但是我无法对扩展进行测试。

基本上,我希望能够指定一个源目录、一个包含搜索项的文件和一个要搜索的扩展名。

现在,我意识到可能有更快的方法来做到这一点,例如

grep -f searchterms.txt *.end > allchanges.end.res

但我可能需要对文件进行其他处理,我想将它们保存到单独的文件中:因此 bing.end、bong.end 将被 grep 到 bing.end.res, bong.end.res .

请告诉我,我有多蠢 ;-)


为了完整起见,这是最后一部分,工作,感谢@chepner 和@Gordon Davisson:

echo "Searching '$directory' ..."
for file in "${directory}"/*; do
    [ -e "$file" ] || continue
    # show which files will be processed
    if [[ $file = *.${extension#.} ]]; then
        printf "Processing %s \n" "$file"
        head -n 1 "${file}" > "${file}.res"
        grep -f $searchterms "${file}" >> "${file}.res"
    fi
done

您只需要将 * 排除在引号之外,这样它就不会被视为文字 *:

for file in "${directory}"/*; do

与大多数语言不同,引号不定义字符串(因为 bash 中的所有内容都已经是字符串:它是唯一的数据类型)。他们只是转义引号内的每个字符。 "foo"\f\o\o 完全相同,后者(因为转义大多数字符实际上没有任何效果)与 foo 相同。无论是否引用,所有未被 word-splitting 个字符分隔的字符都是同一单词的一部分。

http://shellcheck.net 会捕捉到这一点,尽管不是最有用的错误消息。 (它还会捕获您没有引用但应该引用的其他参数扩展。)