Grep은 파일 목록을 소스로 사용하여 문자열을 찾습니다.

Grep은 파일 목록을 소스로 사용하여 문자열을 찾습니다.

일반 텍스트 파일이 있고 각 줄은 파일의 경로입니다. 이제 grep이 파일에서 문자열을 찾아야 합니다 .

이 파일을 "검색 소스"로 사용할 수 있는 방법이 있습니까 grep? 아니면 bash의 모든 경로를 복사하여 붙여넣어야 합니까?

grep둘째: 한 줄에 여러 파일을 검색 소스로 제공할 수 있는 방법이 있나요 ? 좋다

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

한 줄에 하나의 파일 이름으로 구성된 파일 목록이 있는 경우 여러 가지 가능성이 있습니다. 파일 이름에 외국 문자가 없으면 다음 중 하나가 작동합니다.

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명령줄로 바꿉니다. 파일 이름에 공백이나 쉘 와일드카드 문자( )가 포함되어 있으면 \[?*실패합니다 . 목록이 너무 커서 명령줄 길이 제한(많은 시스템에서 약 128kB 이상)을 초과하는 경우에도 실패합니다. 파일 이름에 공백이 포함되어 있으면 두 번째 명령이 실패합니다 \"'. 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*

관련 정보