将工作命令转换为获取参数的 shell 脚本文件

将工作命令转换为获取参数的 shell 脚本文件

嗨我的工作命令是:

grep -l "my text" file*.ext|xargs ls -lart

这个命令对我来说非常有用,我想创建一个 shell 文件,用更少的输入来完成它,如下所示:

fn "my text" file*.ext

我来到这个shell脚本文件:

grep -l "$1" "$2"|xargs ls -lart

这不起作用,甚至第一部分也不起作用:

grep -l "$1" "$2"

返回 null

答案1

您的脚本需要采用两个以上的参数。

在shell执行grep命令之前

grep -l "my text" file*.ext

文件名通配模式file*.ext扩展到所有匹配的文件名。因此最终运行的命令行将是

grep -l "my text" file1.ext file2.ext file3.ext

(如果这些是与模式匹配的文件)

因此,您的脚本可能看起来像

#!/bin/sh

pattern=$1
shift

grep -l -e "$pattern" "$@" | xargs ls -lrt

在这里,模式被保存到一个变量中,然后从命令行参数列表中移出。其余参数是文件名列表(如果命令行上的文件名通配模式匹配)并且可在"$@".

确保双引号$@。这将$@扩展到单独引用的命令行参数的列表。

我已删除该-a选项,ls因为在提供要列出的显式文件名时不需要它。我还使用grepwith-e来指定模式,因为带有初始破折号 ( -) 的模式可能会造成混淆grep


如果不是为了排序,我会建议使用以下find命令而不是管道(正确处理带有空格和换行符的文件名):

find . -type f -name "$filepattern" -exec grep -q -e "$pattern" {} ';' -ls

这会查找名称与 中的内容匹配$filepattern、内容与 中的内容匹配的文件$pattern,然后生成ls -l类似的输出。搜索在当前目录中递归执行。

作为脚本的一部分:

#!/bin/sh

pattern=$1
filepattern=$2

find . -type f -name "$filepattern" -exec grep -q -e "$pattern" {} ';' -ls

脚本需要以这样的方式调用:在调用它时,shell 不会扩展文件名通配模式:

$ ./script.sh 'my text' 'file*.ext'

答案2

为了使其更安全,尽管依赖 GNU 扩展:

#! /bin/sh -
pattern=${1?pattern required}; shift
: "${1?no filename specified}"
grep -l --null -e "$pattern" -- "$@" |
  xargs -r0 ls -lrtd --

使用--null/ -0,我们可以避免包含空格、引号或反斜杠的文件名出现问题。

这样-e "$pattern",我们就可以避免以 开头的模式出现问题-

使用--,我们可以避免以 . 开头的文件名出现问题-

使用-d,我们可以避免目录类型的文件恰好匹配时可能出现的混淆。

使用-r,如果没有匹配的文件,我们可以避免列出当前目录。

请注意,对于大量文件,可能会选择对部分文件列表xargs运行多次调用,这意味着输出将无法按时间正确列出。ls

另请注意,这-意味着 stdin 为,但在当前目录中grep调用的文件为。 GNU将输出(或其翻译成您的语言)。如果要指定当前目录中调用的文件,请使用.-lsgrep -l(standard input)-./--

相关内容