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


8

我目前正在使用

watch head -n 17 *

该方法有效,但也显示了直到17号的所有行。基本上,我只想显示使用当前方法显示的每个文件的最后一行。我该如何实现?

为了举例,让我们减少行nr。至7。

示例文件:

1
2
3
4
5
6
7
8

这行:

watch head -n 7 *

输出

1
2
3
4
5
6
7

我要的地方:

7

Answers:


15

使用GNU awk

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

给出如下输出:

        ./file1[17] line17
  ./short-file2[05] line 5 is the last

请注意,./*全局watch调用一次仅扩展一次。

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

如果$(reboot)当前目录中有一个名为的文件,它将重新启动。

使用-x,我们告诉watch您跳过外壳程序并直接执行命令。或者,您可以执行以下操作:

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

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

watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'

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

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

输出如下:

./file1: line17
./short-file2: line 5 is the last

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


感谢您的安全说明。实际上,您是对的,我的命令也没有执行我需要执行的操作,即监视添加的文件,您的版本也可以解决该问题。唯一的缺点是我需要学习AWK,尽管这样做find . -exec是这样的:D
Felix Dombek

11

结合headtail喜欢这两个示例:

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

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

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

watch 'for f in *; do head -n 17 -- "$f" 2>/dev/null | tail -n 1 ; done'

请注意该2>/dev/null部分,因为*将匹配目录和您可能没有读取权限的任何文件,这会产生错误消息,您可能希望将其隐藏,所以它是必需的。


0

使用find,exec和sed的另一种方法

watch find . -type f -name \"*\" -exec sh -c \'\( printf '%-50s ' {} \; sed -n 17p {}\)\' \\\;

1
对于少于17行的文件不起作用。仔细阅读问题。
通配符
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.