如何选择“locate”的结果之一并让它用指定的应用程序打开

如何选择“locate”的结果之一并让它用指定的应用程序打开

我有一个名为的 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上执行,2IE,如果这是我在之前的搜索结果中输入的内容,它将执行:

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第二个参数着色并不总是有效。传递-rtolocate使其使用正则表达式,但 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]}"

这看起来像是一个简单的答案(取决于主题的复杂性)。

但如果结果超过一定数量就不够好!在这种情况下,我们需要类似moreless

相关内容