【问题标题】:Shell Script - LinuxShell 脚本 - Linux
【发布时间】:2025-12-20 18:55:10
【问题描述】:

我想写一个非常简单的脚本,它接受一个进程名,并返回包含进程名的最后一个文件名的尾部。

我写了类似的东西:

#!/bin/sh
tail $(ls -t *"$1"*| head -1) -f

我的问题:

  1. 我需要第一行吗?

  2. 为什么ls -t *"$1"*| head -1 | tail -f 不起作用?

  3. 有更好的方法吗?

【问题讨论】:

  • 脚本“返回”它的状态——成功为零,失败为非零。你希望它的“输出”是一个文件名。这是 grok 的一个重要区别。

标签: linux shell scripting


【解决方案1】:

1:第一行是所谓的she-bang,阅读描述here

在计算中,shebang(也称为 hashbang、hashpling、pound bang 或 crunchbang) 指的是字符 “#!”当他们是前两个时 解释器指令中的字符 作为文本文件的第一行。在一个 类 Unix 操作系统, 程序加载器需要存在 这两个字符作为指示 该文件是一个脚本,并尝试 使用 其余部分指定的解释器 文件的第一行

2:tail 无法从标准输入中获取文件名:它可以将标准输入上的文本或文件作为参数。请参阅man page

3:我没有想到更好的解决方案:注意包含空格的文件名:这不适用于您当前的解决方案,您需要在 $() 块周围添加引号。

【讨论】:

  • 你的意思是“2.tail”吗?
  • 是的,奇怪的标记错误,有时我不懂标记!
  • 好的,但是第一行是强制性的吗?我将运行脚本的 shell 无论如何都会运行脚本。我正在从 shell 运行脚本。所以我的问题是我需要第一行做什么?
  • @Idan 认为第一行告诉操作系统使用什么程序来运行您的脚本。因此,无需通过调用“sh myscriptname”来运行它,您只需输入“./myscriptname”或“myscriptname”即可运行它。
【解决方案2】:

$1包含第一个参数,进程名实际上在$0中。但是,这可以包含路径,因此您应该使用:

#!/bin/sh
tail $(ls -rt *"`basename $0`"*| head -1) -f

您还必须使用ls -rt 来首先获取最旧的文件。

【讨论】:

  • 即使问题“采用进程名称 [...] 包含进程名称的文件名”存在一些歧义,我将其解释为“采用进程名称 [...] 文件包含那个进程名称的名称”,所以它是 $1 而不是我们引用的 $0。
【解决方案3】:

如果您从 shell 运行脚本,则可以省略 shebang,在这种情况下,内容将由您当前的 shell 实例执行。在许多情况下,这不会造成任何问题,但这仍然是一种不好的做法。

【讨论】:

  • 这取决于你如何运行脚本。如果您说sh /path/to/script,则不需要 shbang。如果您说/path/to/script,那么最好包含一个shebang,即使您只是从另一个shell 运行它。
【解决方案4】:

继@theomega 的回答和@Idan 在 cmets 中的问题之后,除其他外,还需要 she-bang,因为某些 UNIX / Linux 系统具有多个命令 shell。

每个命令 shell 都有不同的语法,因此 she-bang 提供了一种方法来指定应该使用哪个 shell 来执行脚本,即使您没有在运行命令中通过键入(例如)

./myscript.sh

而不是

/bin/sh ./myscript.sh

请注意,she-bang 也可用于以非 shell 语言(如 Perl)编写的脚本中;如果你放

#!/usr/bin/perl

在脚本的顶部。

【讨论】:

  • 呃,bash 是“Bourne again shell”。 sh 通常是指向其他 shell 的链接,例如 dash(Debian Almquist shell)或 bash(尽管 sh 是实际上是(例如)Solaris 上的 Bourne shell)。
最近更新 更多