如何观看文件夹文件中的第 17 行(或最后一行,如果更少)?

Fel*_*bek 8 bash watch head

我目前正在使用

watch head -n 17 *
Run Code Online (Sandbox Code Playgroud)

哪个有效,但也显示了第 17 行之前的所有行。基本上,我只想显示我当前方法显示的每个文件的最后一行。我怎样才能做到这一点?

例子

例如,让我们减少线 nr。到 7. 所以:

示例文件:

1
2
3
4
5
6
7
8
Run Code Online (Sandbox Code Playgroud)

这一行:

watch head -n 7 *
Run Code Online (Sandbox Code Playgroud)

产出

1
2
3
4
5
6
7
Run Code Online (Sandbox Code Playgroud)

我想要的地方:

7
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 15

使用 GNU awk

watch -x gawk '
  FNR == 17 {nextfile}
  ENDFILE   {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}' ./*
Run Code Online (Sandbox Code Playgroud)

这给出了如下输出:

        ./file1[17] line17
  ./short-file2[05] line 5 is the last
Run Code Online (Sandbox Code Playgroud)

请注意,./*glob 仅在watch调用时扩展一次。

watch head -n 17 *是一个任意命令注入漏洞,因为它的扩展*实际上被 shell 解释为 shell 代码,watch调用解释其参数与空格的连接。

如果$(reboot)当前目录中有一个文件被调用,它会重新启动。

使用-x,我们告诉watch您跳过 shell 并直接执行命令。或者,你可以这样做:

watch 'exec gawk '\''
  FNR == 17 {nextfile}
  ENDFILE   {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}'\'' ./*'
Run Code Online (Sandbox Code Playgroud)

为了watch运行一个 shell,它会./*在每次迭代时扩展那个glob。watch foo bar实际上与 相同watch -x sh -c 'foo bar'。使用时watch -x,您可以指定所需的 shell,例如选择一个更强大的 shell zsh,可以进行递归全局搜索并限制为常规文件:

watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'
Run Code Online (Sandbox Code Playgroud)

没有gawk,您仍然可以执行以下操作:

watch '
  for file in ./*; do
    [ -s "$file" ] || continue
    printf "%s: " "$file"
    head -n 17 < "$file" | tail -n 1
  done'
Run Code Online (Sandbox Code Playgroud)

给出如下输出:

./file1: line17
./short-file2: line 5 is the last
Run Code Online (Sandbox Code Playgroud)

但这会降低效率,因为它意味着每个文件运行多个命令。


hyd*_*yde 11

在这两个示例中组合headtail喜欢:

$ seq 1 80 | head -n 17 | tail -n 1
17

$ seq 1 10 | head -n 17 | tail -n 1
10
Run Code Online (Sandbox Code Playgroud)

因此,要解决您的实际问题,命令是:

watch 'for f in *; do head -n 17 -- "$f" 2>/dev/null | tail -n 1 ; done'
Run Code Online (Sandbox Code Playgroud)

请注意该2>/dev/null部分,它是必需的,因为 * 将匹配目录和您可能无权读取的任何文件,这将产生错误消息,您可能想要隐藏这些消息。