Grep はファイルのリストをソースとして使用して文字列を検索します。

Grep はファイルのリストをソースとして使用して文字列を検索します。

プレーンテキストファイルがあり、各行はファイルのパスです。grepこのファイルで文字列を探す必要があります。

このファイルを「検索ソース」として使用する方法はありますかgrep?それとも、bashのすべてのパスをコピーして貼り付ける必要がありますか?

grep第二:1行に複数のファイルを検索ソースとして提供する方法はありますか?良い

egrep --color -i "test" /tmp/1.txt, /tmp/2.txt...?

答え1

何について

fgrep <pattern> `cat file_list.txt`

「代わりに」正しい引用符を追加してください。 - あなたが欲しいものを理解するなら

答え2

答えがやや曖昧な質問をいくつか提起しているので、この答えを書き直しました。この答えで霧が少しでも解消されることを願っています。

注:xargs引数が多すぎてコマンドラインで使用可能なメモリを超える場合は、位置引数(args)をプログラムに渡すのに適しています。

コメントはスクリプトにあります。

#!/bin/bash

  rm -f "/tmp/file   "*

# Create some dummy test files and write their names to /tmp/list
  for x in {A..D} ;do 
      echo "text-$x" >"/tmp/file   $x"
      echo "/tmp/file   $x"
  done >"/tmp/list"

# Set up Quirk 1... with an escaped char \A in the file-name.
        # Replace one of the file-names in the list with a quirky but valid one.
          echo 'quirk 1. \A in filename' >'/tmp/file   \A'
          sed -i 's/A/\\A/'  "/tmp/list"

        # The next two lines show  that 
        #            'file   \A' is in the list      and DOES exist.
        #            'file   A'  is NOT in the list, but DOES exist.
        # Therefore, 'file   A'  should NOT produce a 'grep' match
          echo "Quirk 1. backslash in file-name"  
          echo "   ls:"; ls -1 '/tmp/file   '*A    |nl  
          echo " list:"; sed -n '/A/p' "/tmp/list" |nl
          echo "===================="

# Set up Quirk 2... with $D in the file name
        # Replace one of the file-names in the list with a quirky but valid one.
          echo 'quirk 2. $D in filename' >'/tmp/file   $D'
          sed -i 's/D/\$D/'  "/tmp/list"
          D='D' 
        # The next two lines show  that 
        #            'file   $D' is in the list      and DOES exist.
        #            'file   D'  is NOT in the list, but DOES exist.
          echo "Quirk 2. var \$D=$D in file-name"  
          echo "   ls:"; ls -1 '/tmp/file   '*D    |nl  
          echo " list:"; sed -n '/D/p' "/tmp/list" |nl
          echo "===================="

# The regex search pattern
  regex='(A|C|D)'

# Read lines of a file, and use them as positional parameters.
#  Note: 'protection' means protected from bash pre-processing. (eg path expansion) 
# ============================================================
  ###  
  echo 
  echo "========================================"
  echo "Passing parameters to 'grep' via 'xargs'"    
  echo "========================================"
  echo 
  ###
    echo "# Use 'xargs' with the assumption that every file name contains no meta characters."
    echo "# The result is that file names which contain meta characters, FAILS."   
    echo "# So it interprets '\A' as 'A' and whitespace as a delimiter!"
      <"/tmp/list" xargs  grep -E -H "$regex" 
      echo =====; echo "ERROR: All files in the sample list FAIL!" 
      echo =====; echo
  ###  
    echo "# Use xargs -I{} to avoid problems of whitespace in filenames"
    echo "# But the args are further interpreted by bash, as in escape '\' expansion."
    echo "# Bash still interprets xarg's '\A' as 'A' and so 'grep' processes the wrong file"
    echo "# However the -I{} does protect the $D from var expansion"
      <"/tmp/list" xargs -I{} grep -E -H "$regex" {}
      echo =====; echo "ERROR: The 1st line refers to 'file   A' which is NOT in the list!" 
      echo =====; echo
  ###  
    echo "# Use xargs -0 to avoid problems of whitespace in filenames"
    echo "# 'xargs -0' goes further with parameter protection than -I." 
    echo "# Quotes and backslash are not special (every character is taken literally)" 
      <"/tmp/list" tr '\n' '\0' |xargs -0 grep -E -H "$regex"
      echo  ==; echo "OK" 
      echo  ==; echo
  ###
  echo "====================================="
  echo "Passing parameters directly to 'grep'"    
  echo "====================================="
  echo 
  ###
    echo "# Use 'grep' with the assumption that every file name contains no meta characters."    
    echo "# The result is that file names which contain meta characters, FAILS."   
      grep -E -H "$regex" $(cat "/tmp/list") 
      echo =====; echo "ERROR: All files in the sample list FAIL!" 
      echo =====; echo
  ###  
    echo '# Set bash positional parameters "$1" "$2" ... "$n"'  
    echo "# Note: destructive... original parameters are overwritten"
    echo '#   and, you may need to reset $IFS to its original value'
    IFS=$'\n'
    set $(cat "/tmp/list") 
    grep -E "$regex" "$@"
      echo  ==; echo "OK" 
      echo  ==; echo
  ###
    echo '# Set bash positional parameters "$1" "$2" ... "$n"'  
    echo '# Note: non-destructive... original parameters are not overwritten' 
    echo '# Variable set in the sub-shell are NOT accessible on return.'
    echo '# There is no need to reset $IFS'
    ( IFS=$'\n'
      set $(cat "/tmp/list") 
      grep -E "$regex" "$@" )
      echo  ==; echo "OK" 
      echo  ==; echo
  ### 
    echo '# Using bash array elements "${list[0]}" "${list[1]}" ... "${list[n-1]}"'
    echo '# Note: you may need to reset $IFS to its original value'
    IFS=$'\n'
    list=($(cat "/tmp/list")) 
    grep -E "$regex" "${list[@]}"
      echo  ==; echo "OK" 
      echo  ==; echo
  ### 

これが出力です

Quirk 1. backslash in file-name
   ls:
     1  /tmp/file   A
     2  /tmp/file   \A
 list:
     1  /tmp/file   \A
====================
Quirk 2. var $D=D in file-name
   ls:
     1  /tmp/file   D
     2  /tmp/file   $D
 list:
     1  /tmp/file   $D
====================

========================================
Passing parameters to 'grep' via 'xargs'
========================================

# Use 'xargs' with the assumption that every file name contains no meta characters.
# The result is that file names which contain meta characters, FAILS.
# So it interprets '\A' as 'A' and whitespace as a delimiter!
grep: /tmp/file: No such file or directory
grep: A: No such file or directory
grep: /tmp/file: No such file or directory
grep: B: No such file or directory
grep: /tmp/file: No such file or directory
grep: C: No such file or directory
grep: /tmp/file: No such file or directory
grep: $D: No such file or directory
=====
ERROR: All files in the sample list FAIL!
=====

# Use xargs -I{} to avoid problems of whitespace in filenames
# But the args are further interpreted by bash, as in escape '\' expansion.
# Bash still interprets xarg's '\A' as 'A' and so 'grep' processes the wrong file
# However the -I{} does protect the D from var expansion
/tmp/file   A:text-A
/tmp/file   C:text-C
/tmp/file   $D:quirk 2. $D in filename
=====
ERROR: The 1st line refers to 'file   A' which is NOT in the list!
=====

# Use xargs -0 to avoid problems of whitespace in filenames
# 'xargs -0' goes further with parameter protection than -I.
# Quotes and backslash are not special (every character is taken literally)
/tmp/file   \A:quirk 1. \A in filename
/tmp/file   C:text-C
/tmp/file   $D:quirk 2. $D in filename
==
OK
==

=====================================
Passing parameters directly to 'grep'
=====================================

# Use 'grep' with the assumption that every file name contains no meta characters.
# The result is that file names which contain meta characters, FAILS.
grep: /tmp/file: No such file or directory
grep: \A: No such file or directory
grep: /tmp/file: No such file or directory
grep: B: No such file or directory
grep: /tmp/file: No such file or directory
grep: C: No such file or directory
grep: /tmp/file: No such file or directory
grep: $D: No such file or directory
=====
ERROR: All files in the sample list FAIL!
=====

# Set bash positional parameters "$1" "$2" ... "$n"
# Note: destructive... original parameters are overwritten
#   and, you may need to reset $IFS to its original value
/tmp/file   \A:quirk 1. \A in filename
/tmp/file   C:text-C
/tmp/file   $D:quirk 2. $D in filename
==
OK
==

# Set bash positional parameters "$1" "$2" ... "$n"
# Note: non-destructive... original parameters are not overwritten
# Variable set in the sub-shell are NOT accessible on return.
# There is no need to reset $IFS
/tmp/file   \A:quirk 1. \A in filename
/tmp/file   C:text-C
/tmp/file   $D:quirk 2. $D in filename
==
OK
==

# Using bash array elements "${list[0]}" "${list[1]}" ... "${list[n-1]}"
# Note: you may need to reset $IFS to its original value
/tmp/file   \A:quirk 1. \A in filename
/tmp/file   C:text-C
/tmp/file   $D:quirk 2. $D in filename
==
OK
==

答え3

一度に複数のファイルを検索するには、コマンドラインの最後にすべてのファイルをスペースで区切って入力します。

grep -i test /path/to/file /some/other/file

ワイルドカードパターンを使用できます。

grep -i test README ChangeLog *.txt

1行に1つのファイル名で構成されるファイルのリストがある場合は、いくつかの可能性があります。ファイル名に外国文字がない場合は、次のいずれかが機能します。

grep -i test -- $(cat list_of_file_names.txt)
<list_of_file_names.txt xargs grep -i test -H --

最初のコマンドはコマンドの出力をcat list_of_file_names.txtコマンドラインに置き換えます。ファイル名にスペースまたはシェルワイルドカード文字()が含まれていると\[?*失敗します。リストが大きすぎてコマンドラインの長さ制限(多くのシステムで約128 kB以上)を超えると失敗します。ファイル名にスペースが含まれていると、2番目のコマンドは失敗します\"'egrepコマンドラインの長さの制限が必要な場合は、複数回実行するように処理します。この-Hオプションを使用すると、grep単一ファイルとして呼び出されても、一致するファイルの名前が常に印刷されます。--最初のファイル名がで始まる場合は、-オプションではなくファイル名として扱われていることを確認してください。

改行を除くすべての文字を含むことができるファイル名を処理する安全な方法は、改行を除くスペース区切りをオフにしてワイルドカード(ワイルドカード拡張)をオフにすることです。

set -f; IFS='
'
grep -i test -- $(cat list_of_file_names.txt)
set +f; unset IFS

答え4

  1. cat filenames.txt | xargs grep <pattern>

  2. grep <pattern> filename1 filename2 filename*

関連情報