在命令行中移动具有长目录路径的文件,而无需重复目录路径。

有没有办法在执行mv命令时,不需要在第二个参数中输入完整路径?
例如: mv my/file/that/has/a/really/long/path/foo.bar some_magic_operator_that_means_the_same_directory/foo.baz

1有什么原因你不能直接使用cd命令进入目录,然后再从那里使用mv命令呢? - zpletan
我经常发现我在日常工作中要在多个目录下执行这些类型的命令。我经常需要从给定的父目录执行几个命令。 - Finbarr
不知怎么的,我发现在终端中使用!!(双感叹号)可以运行上一条执行的命令。你还可以向上一条命令添加参数/文本,但从未尝试过更改/删除上一条命令中的文本。试试看,如果你成功了,我会像一个答案一样放弃这个问题。祝你好运! - Geppettvs D'Constanzo
记住,在使用cd命令切换到任何路径后,你可以使用cd -立即返回上一级路径。 - bloody
5个回答

你可以使用bash的花括号扩展。这样做:
mv my/file/that/has/a/really/long/path/foo.{bar,baz}

将扩展为:
mv my/file/that/has/a/really/long/path/foo.bar my/file/that/has/a/really/long/path/foo.baz

然后使用这两个参数运行mv命令。有关大括号扩展的更多信息,请参阅http://wiki.bash-hackers.org/syntax/expansion/brace

3真是太棒了。我不知道你能做到这一点。 - Finbarr

作为对大括号扩展的替代方案,您可以使用bash shell的历史扩展功能:
  • !引入一个历史扩展
  • #事件指示符表示当前命令
  • $单词指示符指向最后一个参数
您可以使用类似sed的s/pattern/replacement语法对扩展进行替换,例如:
somecommand path/to/foo.bar !#$:s/.bar/.baz

例子

$ mv -v somepath/Original/Dir3/SubDir1/foo.bar !#$:s/.bar/.baz
mv -v somepath/Original/Dir3/SubDir1/foo.bar somepath/Original/Dir3/SubDir1/foo.baz
'somepath/Original/Dir3/SubDir1/foo.bar' -> 'somepath/Original/Dir3/SubDir1/foo.baz'

如果你想要获取特定的路径(例如,将文件以完全不易通过替换获得的名称移动),你可以使用h修饰符:
$ mv -v somepath/Original/Dir3/SubDir1/foo.baz !#$:h/baz.foo
mv -v somepath/Original/Dir3/SubDir1/foo.baz somepath/Original/Dir3/SubDir1/baz.foo
'somepath/Original/Dir3/SubDir1/foo.baz' -> 'somepath/Original/Dir3/SubDir1/baz.foo'

对于其他选项,包括使用readline键组合来复制最后一个参数,请参阅如何在bash控制台上重复当前输入的参数?

使用变量

  1. 将目录保存在一个变量中:`DIR=./really/long/path/
  2. 使用移动命令:mv "$DIR"foo.bar "$DIR"foo.bz

一行代码实现:DIR=./really/long/path/; mv "$DIR"foo.bar "$DIR"foo.bz


更改目录

  1. 你也可以使用cd命令进入你想要工作的目录:cd ./really/long/path
  2. 然后更改文件名:mv foo.bar foo.bz

一行命令实现:cd ./really/long/path && mv foo.bar foo.bz


1那第二个看起来很熟悉;-) - zpletan
2在最后一行代码中最好使用&&。否则,如果cd失败,mv命令将在错误的目录中运行,有可能覆盖文件。通过使用cd ./really/long/path && mv foo.bar foo.baz,只有当cd成功切换目录时,mv命令才会被执行。 - geirha

你可以尝试一下:
pushd .
cd /really/long/directory/name/
mv whatever.1 whatever.2
popd

1使用以下命令代替:cd /really/long/dir/name/; mv what.1 what.2; cd - - bloody

你可以使用别名命令来缩短目录名称:
alias src='/directory/name/of/source'
alias dst='/directory/name/of/destination'
mv src dst

2-1 alias test='/var/log' ; cd test 的输出为 -bash: cd: test: 没有那个文件或目录 - zpletan
你测试过这个吗?在什么情况下它才能工作呢?据我所知,别名用于替换命令,而不是参数。虽然使用!#$的解决方案会更优雅一些... - pedda