【问题标题】:How do I use line output from a command as separate file names in bash?如何在 bash 中使用命令的行输出作为单独的文件名?
【发布时间】:2013-12-18 19:08:21
【问题描述】:

我正在尝试通过 vim 文本编辑器中的命令行干净地打开多个文件,没有错误/怪癖。我使用 bash 作为我的外壳。具体来说,我想打开当前工作目录中的前 23 个文件。我最初的命令是:

$ ls | head -23 | xargs vim

但是当我这样做时,我会在所有文件打开之前收到以下错误消息:

Vim:警告:输入不是来自终端

vim 退出后,终端中不会显示任何新文本。除了打开一个新终端外,我必须盲目地做一个reset 才能恢复正常的终端。

这似乎在这里讨论:using xargs vim with gnu screen,和:Why does "locate filename | xargs vim" cause strange terminal behaviour?

由于警告发生,xargs 似乎是 vim 的禁忌。 (除非您使用子shell 和输入/输出重定向来做一些复杂的事情,我不太感兴趣作为常用命令。并且使用别名/函数......嗯。)

解决方案似乎是使用 bash 的命令替换。所以我尝试了:

$ vim $(ls | head -23)

但文件中有空格和括号,格式如下:

surname, firstname(email).txt

因此,shell 所做的(也是 xarg 情况下的结果)是提供 surname,firstname(email).txt 作为两个单独的命令参数,让我在 vim 中的文件数量至少是我想要的两倍打开,并且没有个我实际上想打开的文件。

所以,我想我需要以某种方式转义文件名。我试图引用命令:

$ vim "$(ls | head -23)"

然后,shell 将替换的整个输出连接起来,并提供 that 作为单个命令参数,所以我留下了一个超长的文件名,这也不是我想要的。

我还尝试使用find-exec-print-print0-printf 选项、bash 中的各种数组,以及可能有些我不记得的东西。我现在很茫然。

我可以做些什么来使用来自命令的文件名,作为单独的命令参数 shell-quoted,以便它们实际工作?

感谢您的帮助!

【问题讨论】:

  • 请问为什么你想这样做?对于这里的真正的问题,也许有更好的解决方案。
  • 当然:我正在标记作业。总共有46个交卷,前半部分由我标记,后半部分由别人负责。因此,我使用前 23 个文件为这 23 个学生编写我的 cmets,而其他 23 个在工作期间对我不太感兴趣。但是,我仍然想保留另一半文件。否则我会这样做:ls | tail -23 | xargs -d '\n' rm; vim *。 :-)

标签: bash shell vim command-line output


【解决方案1】:

这是一个基于数组的解决方案:

fileset=(*)
vim "${fileset[@]:0:23}"

【讨论】:

  • 这很紧凑。谢谢!有没有办法以某种方式使其成为单线?
  • 我不知道。如果文件使用连续编号方案(file1.txt、file2.txt 等)命名,您可以尝试使用vim file{1..23}.txt
  • 好吧,不好意思。尽管如此,这是一个整洁的解决方案。不幸的是,它们没有以这种模式命名。否则括号扩展肯定是首选解决方案。再次感谢!
【解决方案2】:
xargs -a <(ls | head -23) -d '\n' vim

-a 告诉 xargs 从命名文件而不是标准输入读取参数。 &lt;(...) 让我们将 ls/head 管道的输出传递到需要文件名的地方。

【讨论】:

  • 哇,这正是我想要的。除了lshead 之外,基本上只使用一个实用程序xargs 的单线。我以前不知道&lt;(...)。你介意告诉我这个结构叫什么,以便我可以man bash 它吗?
猜你喜欢
  • 2010-10-17
  • 1970-01-01
  • 2015-11-16
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 2021-10-24
  • 2016-07-14
  • 1970-01-01
相关资源
最近更新 更多