Рекурсивный поиск файлов, которые содержат определенную комбинацию строк в первой строке

noatimedeshabilita las actualizaciones de tiempo de acceso implícitas (aquellas que ocurren como un efecto secundario -de una operación en un archivo ); no afecta las actualizaciones de tiempo de acceso explícito (donde un programa pide explícitamente al sistema operativo que actualice el tiempo de acceso de un archivo ). Cuando touchun archivo, está solicitando explícitamente actualizar los tiempos de acceso y modificación, y eso es lo que sucede.

Puede touchun archivo sin cambiar el tiempo de acceso, utilizando la opción -m; sólo se actualizará la hora de modificación.

3
09.12.2018, 19:18
4 ответа

find+awkраствор:

find./backup -type f -exec \
awk 'NR == 1{ if (/StockID.*SellPrice/) print FILENAME; exit }' {} \;

В случае, если порядок ключевых слов может быть другим -, замените шаблон /StockID.*SellPrice/на /StockID/ && /SellPrice/.


В случае большого количества файлов более эффективной альтернативой будет (обработка сразу нескольких файлов;общее количество вызовов команды будет намного меньше, чем количество совпадающих файлов):

find./backup -type f -exec \
awk 'FNR == 1 && /StockID.*SellPrice/{ print FILENAME }{ nextfile }' {} +
6
28.04.2021, 23:39

egrep +awk:

 egrep -Hrn 'StockID|SellPrice'./backup | awk -F ':' '$2==1{print $1}'
0
28.04.2021, 23:39

С GNU grepили совместимым:

grep -Hrnm1 '^'./backup | sed -n '/StockID.*SellPrice/s/:1:.*//p'

Рекурсивный grep напечатает первую строку каждого файла и напечатаетfilename:1:lineбез чтения всего файла (флаг -m1должен привести к выходу при первом совпадении )и sedнапечатает filename, где часть lineсоответствует образцу.

Это не удастся с именами файлов , которые сами содержат :1:или символы новой строки, но на этот риск стоит пойти вместо того, чтобы создавать медленную комбинацию find+ awk, которая выполняет другую процесс для каждого файла.

1
28.04.2021, 23:39

Чтобы избежать запуска одной команды для каждого файла и чтения всех файлов, с помощью GNUawk:

(unset -v POSIXLY_CORRECT; exec find backup/ -type f -exec gawk '
  /\<StockID\>/ && /\<SellPrice\>/ {print FILENAME}; {nextfile}' {} +)

Или сzsh:

set -o rematchpcre # where we know for sure \b is supported
for file (backup/**/*(ND.)) {
  IFS= read -r line < $file &&
   [[ $line =~ "\bStockID\b" ]] &&
   [[ $line =~ "\bSellPrice\b" ]] &&
   print -r $file
}

или:

set -o rematchpcre
print -rl backup/**/*(D.e:'
  IFS= read -r line < $REPLY &&
   [[ $line =~ "\bStockID\b" ]] &&
   [[ $line =~ "\bSellPrice\b" ]]':)

Или с bashв системах, где встроенные расширенные регулярные выражения поддерживают \<, \>операторы границ слов (в других, некоторые другие, вы также можете попробовать [[:<:]]/ [[:>:]]или \bвместо):

RE1='\<StockId\>' RE2='\<SellPrice\>' find backup -type f -exec bash -c '
  for file do
    IFS= read -r line < "$file" &&
    [[ $line =~ $RE1 ]] &&
    [[ $line =~ $RE2 ]] &&
    printf "%s\n" "$file"
  done' bash {} +
1
28.04.2021, 23:39

Теги

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