我目前正在使用
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
在这两个示例中组合head
并tail
喜欢:
$ 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
部分,它是必需的,因为 * 将匹配目录和您可能无权读取的任何文件,这将产生错误消息,您可能想要隐藏这些消息。
归档时间: |
|
查看次数: |
1329 次 |
最近记录: |