有没有一种单行代码可以让我创建目录并同时移入该目录?


150

我发现自己重复了很多:

mkdir longtitleproject
cd longtitleproject

有没有一种方法可以在一行中完成而不重复目录名称?我在这里重击。




1
mkdir longtitleproject然后cd !^
user262826 '17

Answers:


160

没有内置命令,但是您可以轻松编写一个mkdir随后调用的函数cd

mkcd () {
  mkdir "$1"
  cd "$1"
}

将此代码放在您的~/.bashrc文件中(或~/.kshrcksh用户或~/.zshrczsh用户)。它定义了一个名为的函数mkcd"$1"当您运行该函数时,它将被该函数的参数替换。

这个简单的版本有几个缺陷:

  • 您不能一次创建子目录链。修复:将-p选项传递给mkdir。(这可能是或不希望的,因为它增加了错别字被发现的风险,例如mkcd mydierctory/newsub会很高兴地创建错字,mydierctory以及mydierctory/newsub您打算newsub在现有字词中创建错字的风险mydirectory。)
  • 如果参数开始-,但不只是-,然后mkdircd将它解释为一个选项。如果只是-,那么cd将其解释为意思$OLDPWD。如果+其后跟0或多个数字,则cd在zsh中将其解释为目录堆栈中的索引。您可以通过--在参数前传递来解决第一个问题,但不能解决其他两个问题。如果./参数是相对路径,则可以通过在参数前面加上前缀来解决所有这些问题。
  • mkdir不会跟随CDPATH,但是cd会跟随,因此,如果您设置CDPATH的值不是以开头.(公认的有些不寻常的配置),则cd可能会将您带到与刚刚创建的目录不同的目录。预先计算./为相对路径修复此(它会导致CDPATH被忽略)。
  • 如果mkdir失败,它将尝试执行cd。修复:用于&&分隔两个命令。

仍然相当简单:

mkcd () {
  case "$1" in /*) :;; *) set -- "./$1";; esac
  mkdir -p "$1" && cd "$1"
}

此版本仍然有可能cd进入与mkdir在一种极端情况下创建的目录不同的目录:如果to的参数mkcd包含..并通过符号链接。例如,如果当前目录是,/tmp/here并且mylink是的符号链接/somewhere/else,则mkdir mylink/../foo创建,/somewhere/else/foocd mylink/../foo将更改为foo。在参数中查找符号链接是不够的,因为外壳程序还在其自己的当前目录中跟踪符号链接,因此cd /tmp/mylink; mkdir ../foo; cd ../foo不会更改为新目录(/somewhere/else/foo)而是更改为/tmp/foo。解决此问题的方法是让cd内置..程序首先解析所有路径组件(foo/..如果foo不存在,因此mkdir永远不需要查看任何..)。

我们来看看这个健壮的版本:

mkcd () {
  case "$1" in
    */..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
    /*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
    /*) mkdir -p "$1" && cd "$1";;
    */../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
    ../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
    *) mkdir -p "./$1" && cd "./$1";;
  esac
}

(练习:为什么我在第一次cd调用时使用子外壳?)

如果mkdir失败,我想确保不要更改当前目录。如果shell没有权限更改为当前目录,则使用cd-或$ OLDPWD进行更改是不够的。另外,调用cd会更新OLDPWD,因此我们只希望执行一次(或恢复OLDPWD)。


还有一些不太专业的方法,不必重新输入上一行的单词:

  • 键入cd ,然后Esc .(或Alt+ .)插入上一个命令的最后一个参数。
  • cd !$cd上一个命令的最后一个参数上执行。
  • 按调Up出前一个命令行,然后对其进行编辑以将其更改mkdircd

谢谢!Esc。对我来说似乎最方便,按键顺序是否有特殊含义?
methodofaction

它只是“重复上一个命令的最后一个单词” 的Bash(并继承自ksh,也适用于zsh)序列。我经常使用它。
geekosaur 2011年

30
@Gilles我开始认为“ Gilles”帐户实际上是由一个专家小组共享的。;-)
Keith

@StephaneChazelas /a/b/..//实际上可以工作,但不能工作/a/b/../c。固定。我已经把这个问题提给了更广泛的听众。
吉尔斯2013年

1
mkcd() { mkdir -p "$1" && cd "$1"; }在(我的实例)zsh中似乎没有问题。 mkdir -p /var/tmp/somewhere/else /tmp/here; cd /tmp/here; ln -s /var/tmp/somewhere/else mylink; mkdir -p mylink/../foo && cd mylink/../foo; pwd(包括设置和),显示/tmp/here/foo创建的内容(以及我期望的内容)。 bash错误地创建和更改/var/tmp/somewhere/foo
亚当·卡兹

133

这是您需要的一线。无需其他配置:

mkdir longtitleproject && cd $_

$_以bash表示的变量是上一个命令的最后一个参数。在这种情况下,您刚刚创建的目录的名称。如中所述man bash

_         At  shell  startup,  set to the absolute pathname used to invoke
          the shell or shell script being executed as passed in the  envi
          ronment  or  argument  list.   Subsequently, expands to the last
          argument to the previous command, after expansion.  Also set  to
          the  full  pathname  used  to  invoke  each command executed and
          placed in the environment exported to that command.  When check
          ing  mail,  this  parameter holds the name of the mail file cur
          rently being checked."$_" is the last argument of the previous command.

使用cd $_检索前面的命令,而不是最后一个参数cd !$,因为cd !$给前一个命令的最后一个参数在shell的历史记录

cd ~/
mkdir folder && cd !$

你最终回家(或〜/)

cd ~/
mkdir newfolder && cd $_

你最终在家里的新文件夹下!(或〜/ newfolder)


23
为什么在地球上这不是一个可以接受的答案
JSmyth '16

1
@JSmyth我同意,这是使用本机外壳功能的
单行

我认为OP正在尝试避免使用这两个命令。这个答案(几乎)与doing一样有效mkdir foo && cd foo,这并不方便。
josemigallas

7
该OP是要求不需要重复目录名一行代码,这就是它
赫苏斯·卡雷拉

这是您所指的传统单行代码,或已在文档/教程中看到其他人使用的单行代码。实际上,这里有3个完美答案。这个,@ jordan-harris的一个,然后选择答案。取决于您的设置和首选项。
韦德

30

我几乎不会想出这种行为的脚本,因为我几乎每小时都输入以下内容...

$ mkdir someDirectory<ENTER>
$ cd !$

bash友好地!$用最后一行的最后一个单词代替;即您输入的长目录名。

此外,在这种情况下,文件名补全是您的朋友。如果新目录是文件夹中唯一的文件,则快速双击TAB将为您提供新目录而无需重新输入。

虽然bash允许您编写诸如其他答案所示的常见任务的脚本很酷,但我认为最好学习bash必须提供的命令行编辑功能,这样当您在另一台计算机上工作时,也不会错过语法您的自定义脚本提供的糖。


1
有什么好地方可以找到最重要的bash怪癖?
dominicbri7

@ dominicbri7通常位于“ bash命令行编辑”下。谷歌搜索相同,其结果如下:web.mit.edu/gnu/doc/html/features_7.html更具体地说,!$是Word指示符的示例,请参见 gnu。 org / software / bash / manual / bashref.html#Word-Designators
Rob

17

根据,您对外壳配置文件进行了哪些自定义以提高生产率?,这是我的方法:

# make a directory and cd to it
mcd()
{
    test -d "$1" || mkdir "$1" && cd "$1"
}

这意味着如果目录已经存在,它也可以工作。


4
-pmkdir 的选项将消除错误。
格伦·杰克曼

1
mcd是已经存在的命令。尽管您只是举了一个例子,但我自己使用了它,因为它比mkcd短。
Dharmit

@Dharmit Shah:现有mcd命令是什么?哪个软件包或项目提供此命令?
Mikel

2
mtools提供了mcd命令。它的手册页显示“ mcd命令用于更改MS-DOS磁盘上的mtools工作目录。”
Dharmit

13

如果您使用Oh My Zsh,则有一个名为take的命令可以做到这一点。看起来像这样。

take myfolder

我实际上是偶然发现的。我只是看了一下,它就在Oh My Zsh GitHub Wiki的此作弊文件中列出。这是一个非常有用的命令,显然很容易创建自己。


1
我从来不知道take:)完美!顺便说一句-iTerm2和Oh My Zsh。实际上,这里有3个完美答案。这个,@jesús-carrera的那个,然后选择答案。取决于您的设置和首选项。
韦德

3

或者,您可以即时创建一个简短的变量并使用两次x = longproject ; mkdir $x ; cd $x-我承认,该变量仍然比使用shellscript函数更长:)


0

这是一个值得一提的细微变化:

function mkdir() {
    local dir=$1
    command mkdir "$dir"  &&  cd "$dir"
}

将其添加到您的计算机中~/.bash_profile,然后就可以mkdir正常使用(一旦完成source),除了现在它将运行上面的函数而不是标准mkdir命令。

请注意,这不会按照Gilles接受的答案来验证输入,而是演示了如何(有效)覆盖内建函数。

从文档(略有释义):

command mkdir [args]运行mkdirargs忽略命名任何shell功能mkdir。仅执行shell内置命令或通过搜索PATH找到的命令。如果有一个名为的shell函数ls,则command ls在该函数中运行将执行外部命令,ls而不是递归调用该函数

我相信builtin取得了类似的结果command


您绝对应该引用$dir
Jeff Schaller

@Jeff同意,但是接受的答案包含了所需的所有验证。我只是介绍使用command替代方法。
Arj

0

向BASH,ZSH或KSH添加辅助功能

mkcd在一行中创建对您的环境的命令

echo -e 'mkcd() {\n mkdir -p "$1" && cd $_\n}' >> ~/.${0//-/}rc && . ~/.${0//-/}rc


-1

刚刚使上述答案自动化并制作了一次性可执行脚本:

fun='
mkcd ()
{
    mkdir -p -- "$1" && cd -P -- "$1"
}'

echo "$fun" >> ~/.bashrc

只需将其复制到一个新文件中mkcd.sh,然后在terminal by中运行一次即可bash mkcd.sh。然后执行source ~/.bashrc以使其在当前会话中正常工作。

此后,您可以mkcd some_dir用来创建并直接在该目录中输入。


您建议编写一个脚本(在文件中),其唯一目的是将脚本追加到~/.bashrc文件中(已给出答案)?您如何建议创建此mkcd.sh脚本?也许有一位编辑?这看起来不仅仅是编辑~/.bashrc。与公认的答案相比,这有什么优势?…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………
斯科特(Scott)

我很遗憾地说,但是是的,正如我在回答中所写的那样,我使用了以上答案。确实有效。如果您不相信我,请尝试一下。关于不尝试,我用了整整一天的时间来用bash和python编写这样的脚本。
subtleseeker

我确实尝试过你写的东西。它不能正常工作。
斯科特,
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.