Linux 查找显示路径和文件名的 xargs 命令 grep

Linux find xargs command grep showing path and filename

find /folder/202205??/ -type f | xargs head -50| grep '^Starting'

有20220501 20220502 20220503等等文件夹... 此命令搜索“/folder/202205??/”中所有文件的所有前 50 行,并显示以文本“Starting”

开头的行

我没有grep命令匹配的文件的路径和文件名。 我怎样才能得到这个信息:路径和文件名以及匹配的行用一个简单的命令?

这里的主要问题是 head 不传递有关哪些行来自哪个文件的信息,因此 grep 可以挑选出匹配的行但不显示文件名或小路。 awk 可以将匹配 修剪到 50 行,并且您可以精确控制每次匹配打印的内容。所以像这样:

find /folder/202205??/ -type f -exec awk '/^Starting/ {print FILENAME ": " [=10=]}; (FNR>=50) {nextfile}' {} +

说明:awk 脚本中的第一个子句打印匹配行(前缀为 FILENAME,实际上也包括路径),第二个子句跳到下一个文件当它到达第 50 行时。另外,我使用 find-exec ... + 功能而不是 xargs,只是因为它更干净一点(并且不会 运行 陷入困境带有奇怪的文件名)。使用 + 而不是 \; 终止 -exec 命令会使 运行 分批处理文件(如 xargs),而不是一次处理一个文件。

一个相对便携的基于awk的解决方案,提供

  1. built-in realpath变异检测,

  2. shell-safe single-quotation(和转义)文件名,

  3. grep-类似输出格式:

    • file-full-realpath:line-number:[matched line contents..]

————————————————————————————————————————

  gfind 202…………/ -mindepth 1 
                 -type f 
                 -not -empty 
                 -not -name ".*" -print0 | 

  xargs -0 -n 20 -P 16 dash -c 'nice [mg]awk -e '\''

    # gawk profile, created Fri May  6 23:26:31 2022

    # BEGIN rule(s)

    BEGIN {
     1      __=substr("grealpath", 2^0^system("exit 0 which "\
                      "grealpath | grep -m 1 -ce .   0 "))
     1      FS="^Starting"
    }

    # Rule(s)

  1020  50 < FNR { # 20
    20      nextfile
    }

  1000  FNR == 1 { # 20
    20      _ = getpath(FILENAME, __)
    }

  1000  -NF < -sub("^",(_)":"(FNR)":",[=10=]) {
        print
    }
   
    20  function getpath(_,____,__,___)
    {
    20      return "-"==_ \
            ? "/dev/stdin" \
            : substr((___=RS)*(RS="[=10=]")*gsub(//,"4&",_),
                             \
                    ((__=(____)" -zePq "(_)" ")|getline _)~"",
                     +__*close(__)^(RS=___))(_)
    
    }'\'' "${@}" ' _

我敢肯定这并不完美。但它可能会带来一些新的想法。

请注意,在此解决方案中无法正确处理包含换行符等特殊字符的文件名!!

while IFS=: read -r -a a; do [[ ${a[1]} -gt 50 ]] && break; printf "%s\n" "${a[0]}"; done < <( grep -rnH '^Starting' /folder/202205??/ | sort -t":" -k2,2n )

这个 bash 片段写在一行中,但实际上印刷精美它不止一行。

while IFS=: read -r -a a; do
  [[ ${a[1]} -gt 50 ]] && break
  printf "%s\n" "${a[0]}"
done < <( grep -rnH '^Starting' /folder/202205??/ | sort -t":" -k2,2n )

grep 可以使用 -r 递归遍历目录并显示行号 -n 和文件名 -Hsort 在行号上完成。循环在大于 50 的行号处停止。直到它打印文件名。

根据需要输出行号and/or找到的字符串

如果您需要其他内容中的信息,可以处理行号,简单的 grep 可能会给您带来更好的解决方案:

grep -rnH '^Starting' /folder/202205??/

我确定输出可以放在类似 awk 的地方,如果第二个字段中的数字大于 50,它会停止输出。不幸的是我不是 awk 专家。