目前将 ls 的输出“复制/粘贴”到另一个命令中最有效的方法是什么?

目前将 ls 的输出“复制/粘贴”到另一个命令中最有效的方法是什么?

我遇到这种情况很多

  1. 我在一个大目录中,正在寻找一个我忘记了确切名称的特定文件,因此我输入ls以查看其中的所有文件。

  2. 我看到了我想要的文件

  3. 我需要将此文件作为参数传递给命令行。文件名很复杂。

我目前所做的只是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可防止文件名意外扩展或拆分,这两种情况都可能因使用鼠标复制/粘贴而产生风险。对于前者,请考虑一个包含两个文件的目录:abab*。如果您复制/粘贴该ab*文件,您将得到两个都文件回来,ab先!对于后者,请考虑一个包含三个文件 、aba 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

相关内容