grep がダッシュのあるファイル名と混同される

grep がダッシュのあるファイル名と混同される

ディレクトリにダッシュで始まるファイルが含まれていると、grepが混乱する問題が発生します。

たとえば、「」というファイルがあります------.js。同様の操作を実行するとgrep somestring *エラーが発生します。

grep: unrecognized option '------.js'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

インターネットにこんな質問がたくさん出てくるようですが、検索しても出ませんね。

同様のアプローチを使用して問題を手動で解決できますが、
find . | while read f; do grep MYSTRING "$f"; done
よりシンプルで強力なソリューションがあるかどうかを知りたいです。

私はアーチLinuxを使用しています。

答え1

Romeoの回答を補完し、次の点に注意してください。

grep pattern --whatever

POSIXを探す必要があります。模様--whateverファイルから。オプションではない引数(ここpattern)の後にはオプションを認識してはいけません。

この場合、GNUはgrepPOSIXと互換性がありません。 POSIXLY_CORRECT環境変数(任意の値)をその環境に渡して互換性を持たせることができます。

getopt()getopt_long()これは、コマンドライン引数を解析するためにGNUまたは/の互換性のある実装を使用するほとんどのGNUユーティリティとユーティリティの場合です。

別の注目すべき例外はGNUシェル( )ですが、インタプリタとその組み込み関数のどちらもオプションではなく引数の後にオプションを受け入れません。GNUの方法でオプションを解析することもできません。envenv VAR=x grep --versiongrepenvbashgetopts

とにかく、これはPOSIXLY_CORRECTを保存しません。

grep -e pattern *.js

patternこれにはオプションではなく引数がなく、-eオプションに引数として渡されるため、後でより多くのオプションが許可されます。)

-+したがって、次の内容が特定のツール(または一部のツール)で始まらないことを保証できない場合は、常にオプションの終わりを--とマークすることをお勧めします。

grep -e pattern -- *.js
grep -- pattern *.js

または以下を使用してください。

grep -e pattern ./*.js

(これはgrep -- pattern *whileというファイルがある場合は-役に立ちません。ファイル自体がで始まる場合はgrep pattern ./*代わりにwhileを使用する必要があります。)grep -e "$pattern"grep "$pattern"$pattern-

1990年代半ばには、環境変数を介してオプションと見なされるべきではないパラメータ(通常はglob拡張によって生成されたパラメータ)を区別しようとしましたが、bashこの試みは解決する問題よりも多くの問題を引き起こしたため削除されました。 。getopt()_<pid>_GNU_nonoption_argv_flags_

答え2

「パラメータの終わり」を知らせるgrepオプションを試すことができます。

grep -- <string> <filename>

その後、grepは次のダッシュを引数として無視し、コマンドラインの次の要素として処理するように指示します。

答え3

他の回答でTLDRを公開するには確かに固定する、

grep -e pattern ./*.js

これは--、対応するオプションのないコマンドに対して機能します。かなり広くサポートされていますが、すべてのコマンドがそれを処理できるわけではありません。

(また、-eあいまいさも明確であることに注意してください。模様ダッシュで始めましょう。もちろん、この問題を解決するために同様のアプローチを使用できますが、[-]patternそれはうまくいきませんgrep -F。スキーマがユーザーによって提供されている場合は、問題を引き起こさないのが最善です。 )

「(ほぼ)常に変数を引用」してから、これはおそらくシェルプログラミングで2番目に最も一般的な問題です。ワイルドカードのマッチングとユーザー提供のデータには、先行ダッシュが含まれる場合があり、時々含まれているため、準備することをお勧めします。

答え4

find . -name '-*' -exec rename 's/[- ]//' {} \;

関連情報