検索結果を変数に保存し、出力の周りに一重引用符を追加してファイル名のスペースを保護しました。したがって、forループは完全に機能します。
私の問題は、ファイルの1つをgrepしようとすると、実際にはファイル名の一部として一重引用符があるため、「ファイルが存在しません」というメッセージが表示されることです。
どうすればこの問題を克服できますか?
all_files=$(find . -type f -printf "'%p'")
for file in $all_files
do
grep 'hello' $file ### this says "file.not found because of the single quotes
done
答え1
.txt出力に引用符を追加してファイル名の値を保護していませんfind
。ループはまだ'a filename'
繰り返す必要がある2つの項目として扱われます。ご存知のように、引用符も文字列の一部になります。
代わりに、grep
以下を実行してくださいfind
。
find . -type f -exec grep 'hello' {} \;
これは、grep
見つかった各ファイルに対して一度だけ実行されます。
find . -type f -exec grep 'hello' {} +
これgrep
により、一度にできるだけ多くのファイルが実行されます(したがって、複数のファイルを含むバッチのファイル名も出力し、ファイル名を印刷したくない場合は-h
GNUまたは互換オプションを使用してください)。grep
それでもGNUを使用していますgrep
。
grep -D skip -r 'hello' .
これはgrep
現在のディレクトリで再帰的に実行され、非正規ファイル(と同様-type f
)をスキップしますが、それでも通常のファイルfind
へのシンボリックリンクを見つけます(GNUを使用するのと同じfind -xtype f
)。
答え2
後で繰り返すためにファイルのリストを保存するには、配列に保存することをお勧めします。
そしてbash
:
readarray -td '' all_files < <(find . -type f -print0)
for file in "${all_files[@]}"; do
grep hello "$file"
done
(zsh
同じですがボーナスでソートされたリストを取得します):
all_files=(./**/*(ND.))
for file ($all_files) grep hello $file
答え3
「hello」パターンですべてのファイル名を印刷します。
find . -type f -print0 | xargs -0 -L1 grep -l 'hello'
またはfind
インラインでgrep
find . -type f -exec grep -l 'hello' {} \;
またはもっと簡単です(通常のファイルのみがある場合)。
grep -Rl 'hello' .
答え4
私がこの問題をどのように解決したかに興味がある人のために、私は次のような結論を下しました。
all_files=$( find . -type f -name *.txt -printf '%p' )
while read file
do
grep 'hello' "$filename"
.....
done <<< "$all_files"
私はこれが悪い習慣であることを知っています。ただし、特定のユースケースでは、各ファイル名に対して多くのことを行う必要があります。ただたどるだけではありません。今完璧に動作します。
ありがとうございます!