Grep для строки со списком файлов как источник

Ну, гуманный путь состоит в том, чтобы использовать top. Вот некоторый вывод:

Processes: 62 total, 3 running, 1 stuck, 58 sleeping, 309 threads      10:33:37
Load Avg: 0.47, 0.57, 0.41  CPU usage: 41.78% user, 7.4% sys, 51.17% idle
SharedLibs: 68K resident, 0B data, 0B linkedit.
MemRegions: 20459 total, 751M resident, 0B private, 390M shared.
PhysMem: 535M wired, 1179M active, 1074M inactive, 2787M used, 1310M free.
VM: 133G vsize, 1024M framework vsize, 374887(174) pageins, 0(0) pageouts.
Networks: packets: 208538/119M in, 37975/3259K out.
Disks: 445803/4601M read, 70299/3187M written.

PID   COMMAND      %CPU TIME     #TH  #WQ  #POR #MREG RPRVT  RSHRD  RSIZE
1046  DataDetector 0.0  00:00.13 5/1  3/1  71+  351+  7548K+ 55M+   17M+
1045  top          5.8  00:00.38 1/1  0    25+  72    1468K  7480K  3312K 
1042  less         0.0  00:00.00 1    0    14   34    360K   2312K  1080K 
1040- cvmsComp_i38 0.0  00:00.03 1    0    18   51    912K   2656K  3384K 
1035  csh          0.0  00:00.02 1    0    17   39    732K   2936K  1816K 
1034  login        0.0  00:00.04 1    0    22   239   3028K  29M    6392K 
1032  Terminal     4.0  00:01.13 7    2    114+ 567+  13M+   97M+   33M+
1025  mdworker     0.0  00:00.11 3    1    48   260   5036K  54M    10M 
1021  Safari       0.0  00:09.56 9    2    132  943   34M    122M   103M 
999   mdworker     0.0  00:05.55 3    1    50   476   12M    77M    99M 
997-  thunderbird- 0.3  00:43.25 12   1    155  1546  73M    110M   147M 
981   Preview      0.0  00:01.84 2    1    103  686   21M    111M   45M 
935-  firefox-bin  4.0  01:43.97 25   1    238  1637  81M    138M   205M 
905-  kass         0.0  00:00.06 2    1    57   394   3760K  53M    9028K 

Это не очень дружественный сценарий. Вот ps aux:

USER       PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
nope       935   5.3  5.1  1387680 212912   ??  Ss   10:14AM   1:58.11 /Applica
root        56   1.5  2.0   729352  85588   ??  Ss    4:29AM  14:39.52 /Library
nope      1032   1.2  0.8  2892072  34060   ??  R    10:32AM   0:01.80 /Applica
root        59   0.1  0.5   668812  19976   ??  Ss    4:29AM   2:19.72 /Library
_spotlight  1025 0.0  0.3  2533548  10708   ??  SNs  10:29AM   0:00.12 /System/
nope      1021   0.0  2.5  5133320 105128   ??  S    10:26AM   0:09.57 /Applica
nope       999   0.0  2.4  2666868 101324   ??  SNs  10:24AM   0:05.57 /System/
nope       997   0.0  3.6  1211652 150380   ??  Ss   10:24AM   0:43.56 /Users/n
nope       981   0.0  1.1  2919128  46448   ??  S    10:23AM   0:01.86 /Applica
root       905   0.0  0.2   954736   9028   ??  S    10:12AM   0:00.07 /Library
nope       901   0.0  0.5  1027840  19980   ??  S    10:12AM   0:00.26 /Library
nope       900   0.0  0.3  2814856  13464   ??  S    10:12AM   0:00.06 /System/
nope       879   0.0  0.2   957704  10384   ??  S    10:12AM   0:00.39 /Library

Попытайтесь играть с теми. Я не уверен, каковы заблокированные процессы, но эти команды должны помочь.

Удачи!

2
23.02.2012, 01:51
4 ответа

Я переписал этот ответ, поскольку он поднял некоторые вопросы, ответы, к которым были немного туманными. Я надеюсь, что этот ответ очищает часть вуали...

Примечание: Использование xargs подходит для передачи позиционных параметров (args) к программе, когда существует столько 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
27.01.2020, 21:50
  • 1
    извините, я - Linux newb, мог Вы объяснять более подробно. Спасибо –  opHASnoNAME 22.02.2012, 11:43
  • 2
    И конечно, Gilles set -f версия уменьшает команду до minimilist синтаксиса путем отключения всего globbing с единственным переключателем опции. –  Peter.O 23.02.2012, 12:36

что относительно

fgrep <pattern> `cat file_list.txt`

обратите внимание для помещения корректных кавычек 'и не' - если я понял то, что Вы хотите сделать

4
27.01.2020, 21:50
  • 1
    В пользу использования одинарных левых кавычек сильно препятствуют $() в наше время: fgrep <pattern> $(cat file_list.txt) –  ℝaphink 22.02.2012, 12:19
  • 2
    о веб-камере, которую Это приведет к сбою для файлов, имена которых содержат пробел. –  Peter.O 22.02.2012, 14:02
  • 3
    И будет возможно искать в файлах, не включенных в список, если какое-либо из имен будет включать метасимволы, и расширение соответствует существующим файлам. –  manatwork 22.02.2012, 18:05

Если Вы хотите искать в нескольких файлах сразу, можно ввести их всех в конце командной строки, разделенной пробелами.

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 в командную строку. Это перестало работать, если какие-либо из имен файлов содержат пробел или подстановочные знаки оболочки (\[?*). Это также перестало работать, если список является столь большим, что пробегается через предел длины командной строки (больше, чем приблизительно 128 КБ во многих системах). Вторая команда перестала работать, если какие-либо из имен файлов содержат пробел \"'. Это заботится о выполнении egrep многократно, если предел длины командной строки требует это. -H опция гарантирует это grep будет всегда печатать название файла соответствия, даже если это, окажется, назвали с единственным файлом. -- гарантирует это, если первое имя файла начинается с a -, это будут рассматривать как имя файла и не как опцию.

Безопасный способ обработать имена файлов, которые могут содержать любой символ кроме новых строк, состоит в том, чтобы выключить разделение на пробеле кроме новых строк и выключить globbing (подстановочное расширение).

set -f; IFS='
'
grep -i test -- $(cat list_of_file_names.txt)
set +f; unset IFS
3
27.01.2020, 21:50
  1. cat filenames.txt | xargs grep <pattern>

  2. grep <pattern> filename1 filename2 filename*

1
27.01.2020, 21:50
  • 1
    Остерегайтесь этого xargs требует входа, заключенного в кавычки специфическим способом, таким образом, первая команда не будет работать, если одни из имен файлов будут содержать пробел или \'". –  Gilles 'SO- stop being evil' 23.02.2012, 01:53
  • 2
    , который еще одна причуда то, что, если имя файла или какая-либо строка в "filenames.txt" запускаются с '-', это интерпретируется как опция команды. рассмотрение этого случая и ситуации, что Вы упомянули выше, является там защитой к этому? –  Sriharsha 16.03.2012, 06:47
  • 3
    Поместить -- перед первым именем файла (см. мой ответ). –  Gilles 'SO- stop being evil' 16.03.2012, 10:35

Теги

Похожие вопросы