web-dev-qa-db-ja.com

ディレクトリを作成し、同時にそこに移動できるワンライナーはありますか?

私は自分がたくさん繰り返していることに気づきます:

mkdir longtitleproject
cd longtitleproject

ディレクトリ名を繰り返さずに1行で行う方法はありますか?私はここでバッシュしています。

166
methodofaction

組み込みコマンドはありませんが、mkdirを呼び出してcdを呼び出す関数を簡単に作成できます。

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

このコードを~/.bashrcファイルに入れます(kshユーザーの場合は~/.kshrc、zshユーザーの場合は~/.zshrc)。 mkcdという関数を定義しています。 "$1"は、実行時に関数の引数に置き換えられます。

このシンプルなバージョンにはいくつかの欠陥があります:

  • 一度にサブディレクトリのチェーンを作成することはできません。修正:-pオプションをmkdirに渡します。 (これは、タイプミスが検出されなくなるリスクを高めるため、望ましい場合と望ましくない場合があります。たとえば、既存のmydierctory内にnewsubを作成するつもりであった場合、mkcd mydierctory/newsubmydirectorymydierctory/newsubを喜んで作成します。)
  • 引数が-で始まり、-ではない場合、mkdirおよびcdはオプションとして解釈します。 -だけの場合、cd$OLDPWDを意味すると解釈します。 +の後に0個以上の数字が続く場合、zshのcdはそれをディレクトリスタックのインデックスとして解釈します。引数の前に--を渡すと、最初の問題を修正できますが、他の2つの問題は修正できません。相対パスの場合、引数の前に./を追加することで、これらの問題をすべて修正できます。
  • mkdirCDPATHに追従しませんが、cdは追従します。つまり、CDPATH.で始まらない値に設定した場合(明らかに少し変わった設定です)、cdは以前とは異なるディレクトリに移動する可能性があります作成したばかりです。相対パスの前に./を付加すると、これが修正されます(CDPATHが無視されます)。
  • mkdirが失敗した場合、cdを実行しようとします。修正:&&を使用して2つのコマンドを区切ります。

それでもかなり単純です:

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

このバージョンでは、cdが、あるEdgeケースでmkdirが作成したディレクトリとは別のディレクトリに移動する可能性があります。mkcdへの引数に..が含まれ、シンボリックリンクを通過する場合。たとえば、現在のディレクトリが/tmp/hereであり、mylink/somewhere/elseへのシンボリックリンクである場合、mkdir mylink/../foo/somewhere/else/fooを作成し、cd mylink/../foofooに変更します。シェルはシンボリックリンクも独自の現在のディレクトリで追跡するため、引数でシンボリックリンクを検索するだけでは十分ではないため、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が失敗した場合は、現在のディレクトリを変更しないようにしたいと思います。シェルが現在のディレクトリに変更する権限を持っていない場合、cd-または$ OLDPWDで元に戻すだけでは十分ではありません。また、cdを呼び出すとOLDPWDが更新されるため、一度だけ実行する(またはOLDPWDを復元する)必要があります。


また、前の行のWordを再入力する必要がない、それほど専門的ではない方法もあります。

  • cdと入力して、 Esc. (または Alt+.)前のコマンドの最後の引数を挿入します。
  • cd !$は、前のコマンドの最後の引数でcdを実行します。
  • 押す Up 前のコマンドラインを呼び出して編集し、mkdircdに変更します。

ほぼ1時間ごとに次のように入力するので、この動作をスクリプト化することは決してありませんでした...

$ mkdir someDirectory<ENTER>
$ cd !$

ここでbashは!$最後の行の最後の単語;つまり、入力した長いディレクトリ名。

さらに、このような状況では、ファイル名の補完機能が役立ちます。新しいディレクトリがフォルダー内の唯一のファイルだった場合、 TAB 再入力せずに新しいディレクトリを取得します。

他の回答が示唆しているように、bashがこのような一般的なタスクをスクリプト化できることはクールですが、別のマシンで作業しているときに構文を見逃さないように、bashが提供するコマンドライン編集機能を学ぶ方が良いと思いますカスタムスクリプトが提供する砂糖。

30
Rob

生産性を向上させるためにシェルプロファイルでどのようなカスタマイズを行いましたか? のとおり、次のようにします。

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

つまり、ディレクトリがすでに存在する場合にも機能します。

17
Mikel

Oh My Zshを使用する場合、これを正確に行うtakeというコマンドがあります。こんな感じになります。

take myfolder

私は実際にこれを偶然見つけました。私は見たところ、Oh My Zsh GitHub wikiの this cheatsheat にリストされています。これは非常に便利なコマンドで、明らかに自分で作成するのは非常に簡単です。

16
Jordan Harris

または、オンザフライで短い変数を作成し、それを2回使用することもできますx = longproject ; mkdir $x ; cd $x-私が認めていることは、シェルスクリプト関数を使用するよりもまだ長いです:)

3
sakisk

ディレクトリを作成するスクリプトを作成し、それにcdを実行して、エイリアスを付けました。そして、ここに私がそれを説明する要点があります。

https://Gist.github.com/rehnen/34236d6ff270ccaa74b6#mkdir-like-it-was-meant-to-be

0
Marcus Rehn

ここに言及する価値があるわずかな変形があります:

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

これを~/.bash_profileに追加すると、通常どおりmkdirを使用できます(sourceを実行した後)。ただし、標準ではなく上記の関数を実行します。 mkdirコマンド。

これは、受け入れられた Gillesによる回答 に従って入力を検証しませんが、ビルトインを(効果的に)オーバーライドする方法を示しています。

ドキュメントから (少し言い換えると):

command mkdir [args]mkdirを実行し、argsmkdirという名前のシェル関数を無視します。シェル組み込みコマンドまたはPATHを検索して見つかったコマンドのみが実行されます。 lsという名前のシェル関数がある場合、関数内でcommand lsを実行すると、関数を再帰的に呼び出す代わりに外部コマンドlsが実行されます

builtincommandと同様の結果が得られると思います。

0
Arj

BASH、ZSH、またはKSHへのヘルパー関数の追加

環境にmkcdコマンドを1行で作成します

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