たとえば、私はディレクトリAにいて、Aの下には多くのフォルダ(B、C、Dなど)があり、各フォルダにはファイル「* .out」とサブフォルダがあります。 * .outファイルでテキスト「index123」を検索し、対応するすべてのフォルダー名を出力するスクリプトをAから実行したいと思います。
これが私のスリップです:
#!/bin/sh
FILES=home/A
grep --include=\*.out -rnw $FILES -e "index123" | while read file; do
str1="FILES/$(basename $file)"
echo $str1
done
これはエラーを示しています。
N.B.これは、1行のコードで「検索」することで実行できますが、表示されているwhileループにエラーが表示されるのはなぜですか。
投稿からのように whileループで特定の検索を介してファイルを検索 解決策の1つは、while
ループを使用して次のようになります。
#!/bin/bash
while IFS= read -r d;
grep -q "index123" "$d" && dirname "$d"|awk -F'/' '{print $2}'
done < <(find . -maxdepth 2 -type f -name "*.out")
次のようなディレクトリ構造を想定しています。
A
|-- B
| |-- file1.out
| |-- file2.out
| `-- file3.out
|-- C
| |-- file1.out
| |-- file2.out
| `-- file3.out
|-- D
| |-- file1.out
| |-- file2.out
| `-- file3.out
`-- E
|-- file1.out
|-- file2.out
`-- file3.out
コードの問題は、grep
が次のような出力を生成することです。
./B/file1.out:2:some data which includes the Word index123
./B/file2.out:2:some data which includes the Word index123
./B/file3.out:2:some data which includes the Word index123
./C/file1.out:2:some data which includes the Word index123
./C/file2.out:2:some data which includes the Word index123
./C/file3.out:2:some data which includes the Word index123
./D/file1.out:2:some data which includes the Word index123
./D/file2.out:2:some data which includes the Word index123
./D/file3.out:2:some data which includes the Word index123
./E/file1.out:2:some data which includes the Word index123
./E/file2.out:2:some data which includes the Word index123
./E/file3.out:2:some data which includes the Word index123
それはの出力です
grep --include=\*.out -rnw . -e "index123"
現在のディレクトリとしてA
を使用します。
次に、これらの個々の行でbasename
を実行しようとしますが、basename
は最大2つの引数(パス名とそのパス名から削除するサフィックス)を受け取るため失敗します。 GNU basename
は「余分なオペランド」について文句を言いますが、BSD basename
は誤った使用法について文句を言います。
grep
は、-l
フラグとともに使用すると、ファイルの名前を表示します(つまり、一致した完全な行ではありません)。
これは、スクリプトが単一のコマンドに置き換えられる可能性があることを意味します
grep -w -l "index123" */*.out
これにより、フォームに出力が表示されます
B/file1.out
B/file2.out
B/file3.out
C/file1.out
C/file2.out
C/file3.out
D/file1.out
D/file2.out
D/file3.out
E/file1.out
E/file2.out
E/file3.out
grep
コマンドラインで使用したように-w
を追加しました。 -n
(これも使用している行の番号付け用)は、-l
と一緒に使用することはできません。
あなたのコードから判断すると、これはあなたが望むものです。
フォルダ名だけが必要な場合は、
$ grep -w -l "index123" */*.out | sed 's#/[^/]*##' | sort -u
B
C
D
E
これはすべて、A
が現在の作業ディレクトリであることを前提としていますが、これは問題のケースであるとおっしゃっていたので、問題にはならないはずです。