テキストファイルの特定の行の完全なディレクトリ検索

テキストファイルの特定の行の完全なディレクトリ検索

ルートディレクトリがあり、そのディレクトリ内のすべてのサブディレクトリに移動して、「data.txt」という名前のテキストファイルを見つけようとします。次に、「結果:」で始まるデータテキストファイルからすべての行を抽出しようとします。 「data」というテキストファイルを含むディレクトリを印刷し、結果行を印刷しようとしています。たとえば、ディレクトリ構造が次のような場合:

root
directory1:
  data.txt
directory2:
  // no data.txt here
directory3:
  data.txt

出力は次のようになります。

directory1
Results: .5
directory3
Results: .6
Results: .7

これは私のコードですが、これはうまくいきません。

for d in */; do
> if [[ -f "data.txt" ]]
> then
> echo “$d”
> grep -h “Results:" $data.txt
> fi
> done

このコードを実行すると、何も印刷されません。私はこの解決策が基本的に正しいと思いますが、いくつかの構文問題があります。何をすべきかを知っている人はいますか?

答え1

何が問題であるかについての説明を含むソースコードは次のとおりです。

#!/bin/bash
# That first line is called shebang, if you're interested

for d in */; do
    # 1. You have to check for data.txt in specific location,
    #    so prepend $d directory from your loop to the path:
    if [[ -f "$d/data.txt" ]]
    then
        # 2. “ and ” are good for casual text, but program code uses simple quotes - "
        # 3. You print the name of the every directory you loop over,
        #    even while there are no "Results:" lines there
        echo "$d"
        # 4. Again, $data.txt is weird path - it will result in
        #    directory name with "ata.txt" in your example,
        #    e.g. directory1/ata.txt
        # -  Minor note: better to use regexp's meta-character "^"
        #    to match "Results:" only in the beginning of the lines
        grep -h "^Results:" "$d/data.txt"
    fi
done

スクリプトは次の出力を生成します。

directory1/
Results: .5
directory3/
Results: .6
Results: .7

3番目の問題を解決するには、次の手順を実行する必要があります。

#!/bin/bash

for d in */; do
    if [[ -f "$d/data.txt" ]]; then
        # First, search for the results
        RESULTS=$(grep -h "^Results:" "$d/data.txt")
        # Second, output directory name (and the results)
        # only if the grep output is not empty:
        if [[ -n "$RESULTS" ]]; then
            echo "$d"
            echo "$RESULTS"
        fi
    fi
done

# Produces same output

改善が必要な他の部分は、ディレクトリ/サブディレクトリ/data.txtなどのファイルを見つけるための再帰ディレクトリのサポートです。

#!/bin/bash
# Allow recursive matches
shopt -s globstar

# Loop over the directories recursively:
for dir in **/; do
# ...
# rest of the code

最後に、末尾のスラッシュなしでディレクトリ名を出力するには(例を参照)、次の手順を実行します。

# Instead of
echo "$d"
# Print $d without "/" suffix:
echo "${d%/}"

生成されたスクリプト:

#!/bin/bash
shopt -s globstar

for d in **/; do
    if [[ -f "$d/data.txt" ]]; then
        RESULTS=$(grep -h "^Results:" "$d/data.txt")
        if [[ -n "$RESULTS" ]]; then
            echo "${d%/}"
            echo "$RESULTS"
        fi
    fi
done

作成します(例サブディレクトリを追加しました)。

directory1
Results: .5
directory3
Results: .6
Results: .7
directory4/subdir
Results: .9

関連情報