我遇到这种情况很多:
我在一个大目录中,正在寻找一个我忘记了确切名称的特定文件,因此我输入
ls
以查看其中的所有文件。我看到了我想要的文件
我需要将此文件作为参数传递给命令行。文件名很复杂。
我目前所做的只是ls
使用光标/鼠标突出显示输出,右键单击,然后单击复制,然后将其粘贴到我的命令行提示符中。如果有更好的方法,我宁愿避免这种情况。我知道制表符自动补全,但有时存在例如 abcd abce abcf abcg abcz23 类型的文件的情况,因此制表符补全可能有点笨拙,除非您也有一些建议。例如,即使我能够将输出复制ls
到剪贴板,我也需要某种方法将其范围缩小到我想要的文件,以免将其他文件名也复制到剪贴板。
答案1
查看fzf
,它非常适合像在大列表中查找一个匹配这样的任务。
# Launches an interactive selector listing all the contents of the current
# directory and prints the selected item, storing it in $result
$ result=$(ls | fzf)
答案2
你可以使用bash 的select
构造使用“自由”通配符模式(甚至*
),您确定将包含您想要的文件名。
更改为您想要的目录(或通配符的完整路径),然后:
select mine in *
do
your-command "$mine"
done
输入与您想要的文件相对应的数字,bash 将以该文件名作为参数运行您的命令。起泡沫、冲洗并重复多次,然后按 Control-D 结束循环select
。当然,如果您对文件名有更好的了解,可以收紧通配符。
使用select
可防止文件名意外扩展或拆分,这两种情况都可能因使用鼠标复制/粘贴而产生风险。对于前者,请考虑一个包含两个文件的目录:ab
和ab*
。如果您复制/粘贴该ab*
文件,您将得到两个都文件回来,ab
先!对于后者,请考虑一个包含三个文件 、a
和b
“ a b
”的目录。如果您尝试复制/粘贴“ a b
”文件,您将传递其他文件,a
并且b
!
如果看起来打字太多,您可以将其转换为“一行”:
select mine in *; do your-command "$mine"; done
答案3
如果您使用的是 bash,则可以调用edit-and-execute-command
(请参阅联机帮助页)。这将导致 bash 以您$VISUAL
或$EDITOR
您选择的方式打开当前命令行。然后你可以使用编辑器来获取 ls 的输出。
这很大程度上取决于您的配置,但默认情况下C-xC-e
会这样做。如果你将 bash 设置为 vi 模式,那么esc v
就会执行此操作。
当您保存并编辑编辑器时,bash 将执行该命令。
其他 shell 也具有类似的功能。
答案4
警告
ls
这个答案可能会产生意想不到的结果,因为它取决于不推荐其输出的管道。有关详细信息,请向下滚动到标记为的部分编辑2。
命令替换
命令替换 $(command)
会创建一个子shell,在子shell中执行命令,然后将子shell的输出返回到主shell。
语法是:
main_command_to_run $(ls | grep 'name_of_file')
一个常见的用例(至少对我来说)是解压缩 tar.gz 文件时。
tar -xvzf $(ls | grep 'tar')
一些上下文 - 在这种情况下,我知道当前目录中只有一个 tar 文件,因此我不需要输入 tar.gz 文件的全名
当然,最好ls | grep 'name_of_file'
首先运行来测试您最终是否只得到一个结果,除非您非常有信心文件名是唯一的。
编辑1
正如@roaima 指出的,如果你的文件名有空格,你将需要在表达式中添加双引号:
main_command_to_run "$(ls | grep 'name_of_file')"
使用通配符(通配符)
使用该语法的替代方法$(ls | grep 'name_of_file')
是通过通配符。其中“?”、“*”、“[]”等通配符其他的用于匹配字符。
提供使用星号的示例,星号 ('*') 是匹配零个或多个字符的通配符。因此,正如@roaima 善意提供的那样,名为“foo.tar.gz”的文件的可能用例是:
tar -xvzf *.tar*
编辑2
ls
正如@Hermann 还指出的那样,由于多种原因,管道输出是不可靠的。有关原因的解释,请参阅以下链接:
链接1
链接2
链接3
链接4