変数を拡張してスペースを含むファイルを見つける

変数を拡張してスペースを含むファイルを見つける

検索結果を変数に保存し、出力の周りに一重引用符を追加してファイル名のスペースを保護しました。したがって、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により、一度にできるだけ多くのファイルが実行されます(したがって、複数のファイルを含むバッチのファイル名も出力し、ファイル名を印刷したくない場合は-hGNUまたは互換オプションを使用してください)。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"

私はこれが悪い習慣であることを知っています。ただし、特定のユースケースでは、各ファイル名に対して多くのことを行う必要があります。ただたどるだけではありません。今完璧に動作します。

ありがとうございます!

関連情報