我有一个名为的 bash 脚本findme
,其代码如下:
#!/bin/bash
locate -Abi '*\.'$1 $2 | grep --color=always -ni $2 | less -R
它为我搜索具有指定文件扩展名(提供给脚本的第一个参数)的所有文件,这些文件的文件名中具有模式(下一个提供的参数)。
如果我执行以下命令:
user@machine$ findme pdf classifi
它将搜索文件名中pdf
带有 的所有文件。classifi
所以我可能会得到类似下面的结果。
1:/home/用户/Dropbox/SharedWithFriends/math/分类cations2000.pdf
2:/home/user/Dropbox/SharedWithFriends/math/分类阳离子2010.pdf
问题是: “你能给我一个 bash 脚本代码,在显示结果后询问我一个号码和一个查看器,以自动化我的下一项工作吗?”
例如,如果我输入:
> 2 evince
该脚本在搜索结果的第 nd 项evince
上执行,2
IE,如果这是我在之前的搜索结果中输入的内容,它将执行:
evince /home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf
答案1
findme
这是提取结果的函数的变体,但它不是使用grep
对结果进行编号或less
分页,而是从内部数组中列出它们,然后提示您选择项目和程序。
#!/usr/bin/env bash
readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2" | grep --color=always -i "$2")
for((i=1; i <= ${#results[*]}; i++))
do
printf "%d: %s\n" $i "${results[i]}"
done
read -p "> " item program
$program "${results[item]}"
我在原始脚本中添加了一些引用,以更好地处理文件名中的空格,甚至 grep 参数。我调整了readarray
调用,使结果从索引 1 而不是 0 开始,这样它就对应于 grep 的编号。
答案2
请注意,您的findme
脚本有一些问题:
- 变量替换周围缺少双引号
- 的输出
grep --color=always
产生不能在命令替换中使用的结果。您需要它通过less
,但不要尝试在脚本中重用它。 - grep 和locate 使用不同的模式语法,因此使用
grep
第二个参数着色并不总是有效。传递-r
tolocate
使其使用正则表达式,但 Emacs 语法与 grep 支持的语法略有不同。
在 bash 中,您可以使用mapfile
可靠地将一些行填充到数组中。将其与流程替代使用命令的输出。然后打印该数组并读取用户的输入。
findrun () {
mapfile search_hits <(locate -Abir ".*\.$1" "$2")
print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2"
if read -a cmd; then
set -- "${cmd[@]}"
set -- "$@" "${search_hits[$1]}"
shift
"$@"
fi
}
另一个接口是设置位置参数。这有点棘手,因为您无法更改函数中的位置参数,但是有一个在 bash 中以迂回的方式做到这一点通过使用别名并获取脚本。谨防引用。
alias findrun='. <(echo findrun_prepare \"\$@\"; echo set -- "\"\${search_hits[@]}\"")'
findrun_prepare () {
mapfile search_hits <(locate -Abir ".*\.$1" "$2")
print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2" >&2
}
用法:
findrun pdf classifi
evince "$2"
答案3
基于 Jeff Schaller 给出的解决方案。我找到了解决方案,如果收到您的意见,我会很高兴,以使其变得更好。
#!/bin/bash
readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2")
for((i=1; i <= ${#results[*]}; i++))
do
printf "%d: %s" $i "${results[i]}" | grep --color=always -i "$2"
done
read -p "> " item program
$program "${results[item]}"
这看起来像是一个简单的答案(取决于主题的复杂性)。
但如果结果超过一定数量就不够好!在这种情况下,我们需要类似more
或less