ルートディレクトリがあり、そのディレクトリ内のすべてのサブディレクトリに移動して、「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