如何使用相同的参数执行多个命令?


16

我想知道是否可以在Ubuntu终端中进行连锁操作:

action 1 on objectA . then action 2 on objectA 

不必再重复objectA的名称。

例:

touch file.js && openEditor "$1" 

或类似的东西。


有很多方法可以做到这一点,但要取决于您的需求。什么是objectA?一份文件 ?我们正在谈论什么动作?
Sergiy Kolodyazhnyy

谢谢,通常有效地是一个文件,也可以是一个文件夹
HoCo_18年

3
在这里,&将“触摸”命令发送到后台。如果您打算“打开编辑器,如果触摸成功”,那么你要&&代替
格伦·杰克曼

你为什么要撞这个帖子?您已经有了很多答案,甚至接受了一个答案。
muru

Answers:


27

使用bash 历史扩展,你可以参考使用当前的命令行的第n个字!#:n

$ touch foobar && ls -l !#:1
touch foobar && ls -l foobar
-rw-rw---- 1 steeldriver steeldriver 0 Jun 20 14:54 foobar

$ touch foo bar && ls -l !#:2
touch foo bar && ls -l bar
-rw-rw-r-- 1 steeldriver steeldriver 12 Jun 20 14:58 bar

请问您使用的是哪个bash版本?
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy,这是GNU bash, version 4.3.48(1)-release
steeldriver,

5
您还可以指定一系列单词touch foo bar && ls -l !#:1-2
glenn jackman

1
@HoCo_,!当您在交互式外壳中时,该字符会引入历史扩展表达式-用于在键入时进行即时命令行操作,并且在非交互式脚本中已禁用
Steeldriver

1
@HoCo_在脚本中,您应该提前知道参数是什么-例如,您可以这样做arg1=file.js; touch "$arg1" && openEditor "$arg1"
steeldriver

12

常见用例有一个方便的快捷方式。在您的示例中,您正在执行:

$ touch file.js
$ openEditor <alt>+<.>

在第二个命令中,技巧是在+ openEditor后面写一个空格。这将插入最后一个命令的最后一个参数,即。(如果由于某种原因不能使用,也应该可以使用。)Alt.file.jsAltEsc

由于“对象”通常确实是前一个命令的最后一个参数,因此可以经常使用。它很容易记住,并且将迅速集成到您直观使用的Shell快捷方式集中。

您可以执行很多操作,这里有一篇关于可能性的深入文章:https : //stackoverflow.com/questions/4009412/how-to-use-arguments-from-previous-command

另外,这不仅适用于bash,而且适用于所有所有使用libreadline处理命令行输入的程序。


2
您可以通过结合这数字的说法,例如,以获得第二个参数保持Alt和按2.(或Esc2Esc.),以获得第二到最后一个参数按下Alt+ -,类型2,按Alt+ .(或者Esc-2Esc.)。
甜点

@dessert如果我需要多个参数之一怎么办?例如,我跑echo 1 2 3 4那么我要23下一个命令
wjandrea

@dessert自己找到了!您只需要在它们之间键入其他内容,例如空格。要连接它们,最简单的方法是先键入空格,然后按Backspace。
wjandrea

1
@wjandrea按住Alt并键入2.,按空格键,按住Alt并键入3.–如果要范围,请使用历史记录扩展:!!:2-3
甜点

9

就默认的交互式外壳程序bash和脚本外壳程序dash而言,您可以使用$_来调用last命令的last参数

$ echo "Hello World"; echo same "$_"
Hello World
same Hello World

csh和tcsh具有历史记录引用,特别是对于命令的最后一个单词,您可以使用!$和单个参数- !:<index>

~% echo foo bar
foo bar
~% echo !$
echo bar
bar

% echo bar baz
bar baz
% echo !:1
echo bar
bar

通常,最好将任何内容分配给objectA变量,然后在多个命令,循环等中使用它。或者,可以选择一个函数:

$ foo(){ echo "$@"; stat --print="%F\n" "$@";}
$ foo testdir
testdir
directory

1
我想指出的是,它的$_工作!#:n方式与后者在将命令保存到历史记录之前的扩展方式略有不同。因此,返回历史记录仍会显示带有的命令,$_而while !#:n将被其实际值替换。两者都有其优点和缺点。

3
同样,$_应像往常一样将其引号,否则它将像其他所有内容一样被拆分和聚集。(我们只是在这里看不到它,因为echo它的参数用单个空格连接。)但是,例如,touch "hello there"; ls -l $_ 它将不起作用。
ilkkachu

1
@Dan我认为最大的优点$_是它的便携性。毕竟!#:n是bash特定的。
Sergiy Kolodyazhnyy

3

我建议不要使用钢木匠答案中的历史方法。这依赖于始终脆弱的全球状态。

更好的方法是使用适当的可变参数预先循环所有需要的命令:

$ for c in touch gedit; do $c foo.txt; done

总的来说,有一点问题是Bash不会在发生故障时中止运行,即,它的行为实际上类似于touch foo.txt; gedit foo.txt而不是与链接&&。因此,为了安全起见,您可以添加break

$ for c in touch gedit; do $c foo.txt || break; done

1

编写单行代码时,有时会将重复的内容分配给我在命令中多次使用的shell变量。我可以回忆并对其进行编辑,以使用带有向上箭头,control + a,control + right-arrow的其他arg来使光标靠近t=

t=testloop; asm-link -d "$t.asm" && perf stat -r2 ./"$t"

请注意,这使添加扩展名或名称变体变得容易。

还要注意,我需要;在变量分配之后添加一个变量,因为var=value cmd只需将其设置为该命令的环境变量即可,并且不会影响shell上下文。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.