如何以目录为参数运行一个命令,然后将cd设置为同一个命令?我得到“没有这样的文件或目录”


15

我想构造一个简短的函数来执行以下操作。假设我将文件“ file.tex”移动到我的文档目录中:

mv file.tex ~/Documents

然后,我想cd转到该目录:

cd ~/Documents

我想将其推广到任何目录,以便可以执行以下操作:

mv file.tex ~/Documents
follow

并让该follow命令从上一个命令中读取目标,然后相应地执行。对于一个简单的目录,这不会节省太多时间,但是当使用嵌套目录时,仅使用

mv file.tex ~/Documents/folder1/subfolder1
follow

我认为这将是相对简单的,并且我可以做这样的事情:

follow()
{
    place=`history 2 | sed -n '1p;1q' | rev | cut -d ' ' -f1 | rev`
    cd $place
}

但这似乎不起作用。如果我echo $place,我确实得到了所需的字符串(正在使用进行测试~/Documents),但是最后一条命令返回

No such file or directory

该目录肯定存在。我很茫然。你能帮我吗?


我想指出的是,如果您不介意将其保留file.tex在原始位置,则符号链接是一个很好的选择,因为您只需链接一次,然后它将始终指向最新版本。
Kroltan '16

5
更简单的方法:键入cd alt + .替换上一个命令的最后一个标记。重复以进一步追溯最终代币的历史。(我说的令牌不ARG,因为foo &争夺&作为最终的令牌。)您可以使用一个数值参数(带逃生-3 ALT +。例如)。
彼得·科德斯


Answers:


18

您可以使用变量$_,而不是定义函数,该变量将由扩展为上一个命令的最后一个参数bash。因此使用:

cd "$_"

mv命令。

您也可以使用历史记录扩展:

cd !:$

如果必须使用函数:

follow () { cd "$_" ;}

$ follow () { cd "$_" ;}
$ mv foo.sh 'foo bar'
$ follow 
foo bar$ 

注意:此答案针对您在处理位置参数时使用的确切命令行参数格式。对于其他格式(例如)mv -t foo bar.txt,您需要事先合并特定的检查,然后使用包装器即可。


您的历史记录扩展(cd!:$)可以完美运行。谢谢。但是,另一个(cd“ $ _”)不会:mv file.tex〜/ Downloads / cd“ $ _” bash:cd:__bp_preexec_invoke_exec:没有这样的文件或目录,我很高兴接受您的回答完全正确,并且谢谢。

我一直类型(有点浪费),无论是cd !$cd $(dirname !$)。不知道$_变量!
Kalvin Lee

如果我发生什么事mv -t ~/Documents file.tex,而不是mv file.tex ~/Documents?最重要的是,我不确定这在一般情况下是否可以解决...包装函数或重新实现mv可能更好...
CVn

@MichaelKjörling无法简单地工作..此示例仅是为了说明OP所具有的情况,而不是边缘(或所有)情况
。.– heemayl

您不需要冒号;!$等同于!:$且输入速度更快。
通配符

14

使用标准的bash键绑定,该组合Alt.会将前一个命令行的最后一个参数复制到当前命令行中。因此,输入

$ mv foo ~/some/long/path/
$ cd <Alt><.>

会屈服

$ mv foo ~/some/long/path/
$ cd ~/some/long/path/

甚至比单词少打字follow

为了增加便利,重复Alt.组合将浏览所有先前命令行的最后一个参数。

附录:与此组合键相对应的bash命令名称为yank-last-arginsert-last-argument。可以在bash手册页中的“操纵历史的命令”下找到它,或者在更详尽的《Bash参考手册》中找到它。)


1
那很聪明。谢谢!我不知道这存在。
消防

@Fire我为这些命令添加了参考,因此您可以找到更多有趣的键绑定(立即像以往一样忘记它们)。
Dubu

1
您还可以使用<esc>then .获得与相同的结果<alt>+.,这在重新映射了
capslock

1
我想是@gnur vi(m)用户。;-)
Dubu

6

几乎可以肯定,您会遇到波浪号扩展发生在参数扩展之前的问题,这可以通过一个简洁的示例来解释:

$ cd ~kaz
kaz $ var='~kaz'
kaz $ echo $var
~kaz
kaz $ cd $kaz
bash: cd: ~kaz: No such file or directory

可以使用解决eval。无论如何,您将需要eval,因为您是从历史记录中提取命令,并且它们可以包含任意扩展,例如:

$ mv file.tex ~/Documents/$(compute_folder_name foo-param)/subfolder1
$ follow

(存在一些问题,例如这些值的重新扩展可能不再与发生的原始扩展匹配。假设compute_folder_name是一个使某些全局变量递增的函数。)


4
您不需要eval。(每次)但是可以很好地发现扩展顺序问题。如果您提到在eval此处使用历史记录扩展的更大建议,我认为这将是最佳答案;其他人都没有真正解释为什么原始海报的解决方案无法正常工作。
通配符
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.