询问
我用的是巴什。当我查找文件时,我通常会执行以下操作:
find -name stackexchange.hs
结果通常如下所示:
/youre/the/man/now/dog/stackexchange.hs
/you/are/no/longer/the/dog/dog/stackexchange.hs
/this/is/the/file/i/want/stackexchange.hs
然后我想要执行以下操作之一:
- 选项 1:打开结果列表中的最后一项维姆。
- 选项 2:打开结果列表中的第 N 项维姆。
目前,我用鼠标进行剪切和粘贴。这让我想到了我的问题:
- 是否有一种简单的、一行式的方法可以完成选项 1 和 2?请注意,这种情况正在发生后命令
find
。 - 有没有办法从某种 bash 向量/数组中的标准输出捕获 N 行?
理想用途
$ find -name am_i_really_all_alone.txt
./borges/library/you_are_not_alone.txt
./borges/library/am_i_really_all_alone.txt
$ vim (N)
(语法和语义可能有所不同,但你明白了)
相似之处
类似的问题好像还有好几个。这是我的感知到的差异(我愿意接受启发):
- “使用 find 命令打开找到的文件”专注于创建一行文件,将文件名从管道传输到管道
find
中vim
(或其他任何内容)。就我而言,我想find
先传输,然后再传输(可以这么说)。我的捕获/使用严格遵循后。 - “重用命令 Lind 的最后输出”看起来很不错,但似乎只是重复命令,并没有谈到捕获第N次输出线。坦白说,这让我感到害怕。
- “捕获 Bash 内置的多行输出”很接近,但还不够。
- “终端、shell、tty、控制台等之间的确切区别是什么?”这确实是一本好读的书。
感谢您的帮助!当我还是 90 年代的青少年时,我使用过 *nix/BSD,并被我精疲力竭、酸头的邻居打电话给我,让他帮我安装即插即用声卡的驱动程序吓跑了,我很高兴讨论命令 -将细节与(明显)不那么可怕的个体联系起来。回来的感觉真好。
答案1
这是您的问题的潜在解决方案,应该是合理地(但不是完全)在存在时髦文件名的情况下是安全的(不处理带有换行符的文件名 - 可能可以修复,但可能还潜伏着其他问题)。
两个函数,第一个函数find
使用您传递给它的参数运行,将输出保存在数组中,并显示它们。第二个只是访问该数组的助手。
myfind() {
IFS=$'\n' __last_find_result=($(find "$@"));
printf "%s\n" "${__last_find_result[@]}";
}
myget() {
echo "${__last_find_result[$1]}";
}
使用案例:
$ myfind . -name "c*"
./a b/c d
./.git/config
./.git/hooks/commit-msg.sample
$ vim "$(myget 0)"
# This opens the "./a b/c d" file.
$ vim "$(myget 2)"
# This opens ".git/hooks/commit-msg.sample"
$(myget index)
如果文件名中没有空格或其他麻烦的字符,则不需要在 周围加引号。
将整个输出推送到find
您的环境,这可能是有限的。 (使用临时文件而不是该数组可以解决这个问题,但还有其他问题 - 特别是多个 shell 的并发使用。)
答案2
我的里面有这个.screenrc
:
bind -c pasteline 1 eval copy 'stuff "-Y"' 'paste .'
bind -c pasteline 2 eval copy 'stuff "2-Y"' 'paste .'
bind -c pasteline 3 eval copy 'stuff "3-Y"' 'paste .'
bind -c pasteline 4 eval copy 'stuff "4-Y"' 'paste .'
bind -c pasteline 5 eval copy 'stuff "5-Y"' 'paste .'
bind -c pasteline 6 eval copy 'stuff "6-Y"' 'paste .'
bind -c pasteline 7 eval copy 'stuff "7-Y"' 'paste .'
bind -c pasteline 8 eval copy 'stuff "8-Y"' 'paste .'
bind -c pasteline 9 eval copy 'stuff "9-Y"' 'paste .'
bindkey ¬ command -c pasteline
基本上,在屏幕中,¬1,粘贴光标上方的行,¬2,粘贴光标上方的第二行...等等。您可能想为第 10 行及以上添加更多内容,但我发现在大约第 7 行之后,我宁愿使用鼠标 或screen
的复制模式,也不愿计算行数来获得我想要的行数。
答案3
另一个解决方案是:您可以编写一个交互式脚本,它会自动询问您的选择。这是交互式脚本的代码:
#!/bin/bash
echo "enter your choice : z for last argument or a number for that file"
read choice
case "$choice" in
z) eval vim \$$#;;
*)eval vim \$$choice;;
esac
使用任何名称(如“autofind”)保存此脚本,并使用“find 命令”作为参数调用该脚本,这里是调用脚本的代码:
./autofind `your find command`
但在使用脚本之前检查您的“查找命令”是否给出结果。如果它显示一些结果,则仅使用脚本
答案4
马茨的回答正是我想要的。我稍微扩展了他的代码以允许更多的获取选项。
$ f ~/scripts -name '*.sh'
$ vim $(g foo) # edit all find results matching "foo"
$ vim $(g 1 3 5) # edit find results number 1, 3 and 5
$ vim $(g 3-5) # edit find results 3-5
$ vim $(g 5-) # edit find results 5 to last
$ vim $(g -7) # edit find result 7 from bottom
$ vim $(g 1 4-5 -7 9- foo) # all of the above combined
。
f() {
IFS=$'\n' __last_find_result=($(find "$@"));
printf "%s\n" "${__last_find_result[@]}";
}
g() {
len=${#__last_find_result[@]}
pad=${#len}
numbers=""
if [ "$1" == "-n" ]; then
numbers=1
shift
fi
if [ -z "$1" ]; then
if [ -n "$numbers" ]; then
n=1;
for e in "${__last_find_result[@]}";do
printf "%0${pad}d. %s\n" "$n" "$e"
let n=n+1
done
else
printf "%s\n" "${__last_find_result[@]}"
fi
else
for l in $@;do
if [[ "$l" =~ ([^0-9-]+) ]];then
n=1;
for e in "${__last_find_result[@]}";do
if [[ $e =~ $1 ]]; then
if [ -n "$numbers" ];then
printf "%0${pad}d. %s\n" "$n" "$e"
else
printf "%s\n" "$e"
fi
fi
let n=n+1
done
elif [[ "$l" =~ ^([0-9]+)$ ]];then
let l=l-1
echo "${__last_find_result[$l]}";
elif [[ "$l" =~ ^([0-9]*)(-)?([0-9]*)$ ]]; then
from=${BASH_REMATCH[1]};
dash=${BASH_REMATCH[2]};
to=${BASH_REMATCH[3]};
if [ -z "$from" ]; then # -n
[ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
echo "${__last_find_result[-$to]}";
else # n-m
[ -z "$to" ] && to=${#__last_find_result[@]}
[ $to -gt ${#__last_find_result[@]} ] && to=${#__last_find_result[@]}
let to=$to-1
let from=$from-1
n=$(($from+1))
for i in `seq $from $to`;do
if [ -n "$numbers" ];then
printf "%0${pad}d. %s\n" "$n" "${__last_find_result[$i]}"
else
printf "%s\n" "${__last_find_result[$i]}"
fi
let n=n+1
done
fi
fi
done
fi
}