BashとZshの実際的な違いは何ですか?

カタリナがデフォルトでBashではなくZshに設定されるというニュースで切り替えについて多くの結果が見つかり、シェルスクリプトで問題が発生する可能性がありますが、私はZshに精通していないため、これらの問題が何であるかを知ることができません。

私のシェルスクリプトは実際にはそうではありません。複雑ですが、私はmacOSとLinuxでBashを使用したことがあります。Zshの使用経験はありません。簡単な実用的な比較や、知っておく必要のある特定の障害を誰かが提供できるので、準備に向けて作業を開始できます。 Catalinaがリリースされたときの新しいシェル?

コメント

  • あなたが読んでいるこの騒ぎは、ほとんど何もしません。OSは” default “シェル、新しいユーザーを作成する場合、理由はありません。Bashは’ではありません離れて、あなたはあなたのシェルまたは他のシェルのいずれかとしてそれを使用することができますc
  • ‘が両方を使用し、bashに着陸した人物として話すと、zshに本当に深く不満を感じたのは、その決定だけでした。他の厳密にPOSIXスーパーセットシェルと互換性が必要なスクリプトを書き込もうとしたときに、標準が明らかに悪い設計上の決定を標準化して、正確性についてだらしなくしやすいようにしたときに、POSIXコンプライアンスを破る。残念ながら、その”唯一のもの”はかなり大きなものになる可能性があります。それでも、ksh93は’消えることはなく、bashに真剣に取り組む人は、Appleが出荷する古い3.xリリースを使用しません。’
  • フォローアップとして-昨日Catalinaをインストールし、zshに切り替え、bash_historyをインポートし、bash_profileから私の好みのエイリアスのいくつかをコピーしましたが、何も壊れていないようです。ここにいるすべての人から提供されたすべての情報に感謝し、他の人にも役立つことを願っています。
  • @CharlesDuffy:良いコメントです。 WRTが”深刻な”であり、bash version 3.2.57(1)を使用している:Appleがbash version 3.2.57(1)を使用しているかどうか知っていますかdiv id = “6eb5ca1147”>

システム上の”重要な”については?

回答

まず、いくつかの重要なこと:

  1. bashは消えません。すでにbashを使用している場合は、何も変わりません。変更点は、zshが new アカウントのデフォルトのログインシェルになることだけです。それでも、代わりにbashを選択できます。
  2. スクリプトは影響を受けません。変更されるのは、インタラクティブに使用するためのシェル、つまり端末のシェル(および、crontabなどのログインシェルを使用する他のいくつかのもの)です。 #!/bin/bashやivなどのシバン行で始まる実行権限を持つスクリプトがファイルにある場合id = “2a6c845d50”>

または#!/usr/bin/env bashの場合、以前とまったく同じように機能し続けます。

  • Zshの構文はbashと完全には互換性がありません。 、しかしそれは近いです。たとえば、典型的なエイリアスや関数など、多くのコードが機能し続けます。主な違いは、インタラクティブな構成機能にあります。
  • ここで、切り替えを検討していると仮定します。何年にもわたって可能性があったzshに対して、これが遭遇する主な違いです。これは完全なリストではありません!

    インタラクティブな使用の主な違い

    構成ファイル bash読み取り(主に).bashrc非ログインインタラクティブシェル(ただし、macOSはデフォルトでターミナルでログインシェルを開始します)、.profileまたは、および.inputrc Zsh読み取り(主に).zshrc(すべてのインタラクティブシェル内)および.zprofile(ログインシェル内)。つまり、bashのカスタマイズは適用されません。「移植する必要があります。多くの調整が必要になるため、ファイルをコピーするだけでは不十分です。

    キーバインディングは完全に異なる構文を使用します。 Bashは、 .inputrcbind組み込みを使用してキーを readlineコマンド。 Zshは、 bindkeyビルトインを使用して、キーを zleウィジェットにバインドします。ほとんどのreadlineコマンドにはzshに相当するものがありますが、必ずしも完全に同等であるとは限りません。

    キーバインディングについて言えば、Vi(m)をターミナル内エディターとして使用し、シェルのコマンドラインモードとしては使用しない場合、

    またはVISUALviまたはvimに設定されます。bindkey -eはemacsモードに切り替わります。

    プロンプト :bashは、 PS1 からバックスラッシュエスケープ。Zshは、主に PS1 からプロンプトを設定します。これにはパーセントエスケープ。bashの PROMPT_COMMAND の機能は precmd および フック機能。 Zshには、プロンプトテーマメカニズムなどの便利なメカニズムがあります。

    基本的なコマンドライン履歴メカニズム( / でのナビゲーション、 Ctrl +での検索 R !!とその仲間による履歴拡張、 Alt + または$_)は同じように機能しますが、詳細には多くの違いがあり、ここにリストするには多すぎます。ファイル形式を変更するシェルオプションを変更していない場合は、.bash_history.zsh_historyにコピーできます。

    完了:両方のシェルはデフォルトで基本的な完了モードになり、ほとんどの場合コマンド名とファイル名が完了し、次の方法でファンシーモードに切り替わります。 bashでbash_completionを含めるか、zshでcompinitを実行します。bashがより適切に処理するコマンドと、zshがより適切に処理するコマンドがあります。 Zshは通常より正確ですが、bashが正しくないが賢明なことを行う場合は、あきらめることがあります。コマンドの可能な補完を指定するために、zshには次の3つのメカニズムがあります。

    多くのbashの shopt設定には対応するがありますsetopt inzsh。

    Zsh doe sn “t #は、スクリプト(.zshrcなどを含む)でのみ、デフォルトでコマンドラインのコメント開始として扱います。インタラクティブなコメントを有効にするには、 setopt interactive_comments を実行します。

    スクリプトの主な違い

    (そしてもちろんコマンドラインのパワーユーザーの場合)

    bashでは、$foofooは、空白文字で分割し、空白で区切られた部分ごとに、ワイルドカード文字が含まれていて既存のファイルと一致する場合は、パターンを一致リストに置き換えます。 fooの値を取得するには、"$foo"が必要です。同じことがコマンド置換$(foo)にも当てはまります。 zshでは、$foofooの値であり、$(foo)

    は、2つの例外を除いて、最後の改行を差し引いたものです。引用符で囲まれていない空の変数を展開したために単語が空になった場合、その単語は削除されます(たとえば、a=; b=; printf "%s\n" one "$a$b" three $a$b fiveone、空の行、

    five)。引用符で囲まれていないコマンド置換の結果は空白で分割されますが、ワイルドカードマッチングは行われません。

    Bash 配列には、0から(長さ-1)までのインデックスが付けられます。 Zsh配列には、1から長さまでのインデックスが付けられます。 a=(one two three)の場合、bashでは${a[1]}twoですが、zshでは「 one。bashでは、中括弧なしで配列変数を参照するだけで、最初の要素を取得します。たとえば、$aoneおよび$a[1]one[1]です。zshでは、$aは空でない要素のリストに展開され、$a[1]は最初の要素に展開されます。同様に、bashでは、配列の長さは${#a}です。これはzshでも機能しますが、$#aのように簡単に記述できます。 setopt ksh_arrays を使用して、0インデックスをデフォルトにすることができます。これにより、配列要素を参照するために中括弧を使用する必要もあります。

    Bashには追加の があります。 fooまたはividに一致する@(foo|bar)などのワイルドカードパターン = “61a2882151”> 、これはshopt -s extglobでのみ有効になります。 zshでは、setopt ksh_globを使用してこれらのパターンを有効にできますが、入力が簡単なネイティブ構文(foo|bar)など)。一部にはsetopt extended_globが必要です(doこれを.zshrcに入れると、完了関数でデフォルトでオンになります)。再帰的なディレクトリトラバーサルの**/はzshで常に有効になっています。

    bashでは、デフォルトで、ワイルドカードパターンがどのファイルとも一致しない場合はそのままになります。変更なし。 zshでは、デフォルトで「エラーが発生します。これは通常、最も安全な設定です。ワイルドカードパラメータをコマンドに渡す場合は、引用符を使用します。 setopt no_nomatch setopt null_glob

    bashでは、パイプラインの右側はサブシェルで実行されます。zshでは、親シェルで実行されるため、 somecommand | read outputのようなものを書くことができます。

    いくつかの優れたzsh機能

    bashにはない優れたzsh機能がいくつかあります(少なくとも深刻なエルボーグリースがないわけではありません)。繰り返しになりますが、これは私が最も役立つと思うもののほんの一部です。

    グロブ修飾子 は、タイムスタンプやサイズなどのメタデータに基づいてファイルを照合できます。また、出力を微調整することもできます。構文はかなりわかりにくいですが、非常に便利です。いくつかの例を示します。

    • foo*(.)foo*と、ディレクトリやその他の特別なファイルではなく、通常のファイルへのシンボリックリンク。
    • foo*(*.)
    • foo*(-.):シンボリックリンクではなく、foo*に一致する通常のファイルのみおよびその他の特別なファイル。
    • foo*(-@)foo*に一致するぶら下がっているシンボリックリンクのみ。
    • foo*(om)foo*に一致するファイル。最終変更日、最新のものから順に並べ替えられます。これをls、それは独自のソートを行います。これは特に…
    • foo*(om[1,10])で役立ちます:foo*に一致する最新の10個のファイル、最新のものが最初です。
    • foo*(Lm+1):サイズが1MB以上のfoo*に一致するファイル。
    • foo*(N)foo*と同じですが、これがどのファイルとも一致しない場合は、関係なく空のリストを作成しますnull_globオプションの設定について(上記を参照)。
    • *(D):ドットファイルを含むすべてのファイルに一致します( ...を除く)。
    • foo/bar/*(:t)履歴修飾子):foo/bar内のファイルですが、ファイルのベース名のみが含まれています。 foo/bar/qux.txtqux.txtとして展開されます。
    • foo/bar/*(.:r)foo/barの下にある通常のファイルを取得し、拡張子を削除します。例えば。 foo/bar/qux.txtfoo/bar/quxとして展開されます。
    • foo*.odt(e\""REPLY=$REPLY:r.pdf"\")foo*.odtに一致するファイルのリスト、および.odt.pdfに置き換えます(PDFかどうかに関係なく)ファイルが存在します。

    ここにいくつかの便利なzsh固有の ワイルドカードパターンがあります

    • foo*.txt~foobar*:すべて.txt名前がfooで始まり、foobarではないdiv>ファイル。
    • image<->.jpg(n):ベース名がimageの後に番号が続くすべての.jpgファイル。image3.jpgおよびimage22.jpgですが、image-backup.jpgではありません。 glob修飾子(n)を使用すると、ファイルが番号順にリストされます。つまり、image9.jpgimage10.jpg-nがなくても setopt numeric_glob_sort )。

    ファイルの名前を一括変更するには、zshが非常に便利です。ツール: zmv関数.zshrcの推奨事項:

    autoload zmv alias zcp="zmv -C" zln="zmv -L" 

    例:

    zmv "(*).jpeg" "$1.jpg" zmv "(*)-backup.(*)" "backups/$1.$2" 

    Bashには、変数の値を取得するときに変換を適用するための方法がいくつかあります。 Zshには同じものがいくつかあります

    Zshには、ディレクトリを変更するための便利な機能がいくつかあります setopt auto_cd をオンにすると、(bashにも最近これがあります)。 2引数形式からcd を使用して、現在のディレクトリに近い名前のディレクトリに変更できます。 。たとえば、「/some/where/foo-old/deeply/nested/insideにいて、/some/where/foo-new/deeply/nested/insideに移動する場合は、cd old new

    変数に値を割り当てるには、もちろんVARIABLE=VALUEと記述します。編集変数の値をインタラクティブに実行するには、 vared VARIABLE を実行します。

    最終アドバイス

    Zshには、大文字と小文字を区別しない補完などの定型レシピなど、最も一般的な設定のいくつかをサポートする構成インターフェイスが付属しています。このインターフェイスを(再)実行するには(zsh-newuser-installによって編集された構成ファイルを使用している場合は、最初の行は必要ありません):

    autoload -U zsh-newuser-install zsh-newuser-install 

    すぐに使用でき、構成ファイルがまったくないため、zshの便利な機能の多くは、1990のバージョンとの下位互換性のために無効になっています。 zsh-newuser-installは、オンにするためのいくつかの推奨機能を提案しています。

    Webには多くのzsh構成フレームワークがあります(それらの多くは Github上)。これらは、いくつかの強力な機能を開始するための便利な方法です。コインの裏側は、作者のやり方であなたをロックすることが多いので、「あなたが望むように物事を行うのを妨げることがあります。自己責任で使用してください。

    zshマニュアルには多くの情報がありますが、多くの場合、簡潔でわかりにくい方法で書かれており、例はほとんどありません。オンラインで説明や例を検索することを躊躇しないでください。マニュアルで理解しやすいzshは、見逃してしまいます。 2つの優れたリソースは、 zsh-usersメーリングリスト Unix Stack Exchange です。 Macでのzshへの切り替えに関する記事の広範なコレクションはscriptingosx.comにあり便利ですコマンド履歴を持ち運ぶためのRubyスクリプトは、Githubにあります。

    コメント

    • 今、私は’素晴らしいctrl-oがzshで機能するかどうか疑問に思っています。もちろん、’はbash上のMacOSでも機能しないため、’この回答やサイトとはあまり関係がありません。 ‘クイックオンライン検索でzshのctrl-oに関する情報を見つけることができませんでしたが、bashのctrl-oに関する情報も普遍的に不正確です…
    • @Jasper ‘ bashにこれがあることを知りませんでした。説明を見ると、Coはデフォルトのキーバインディングを使用してzshで同じことを行います。
    • “いくつかの優れたzsh機能が含まれているのを見てうれしかったです。 “セクションを読んで、Appleが非常に一般的なBashからあまり人気のないZshに切り替える決定を下した理由を理解しようと心配して読んでください。 ‘リモートで切り替えを正当化するように説得力のあるものは、まったく見つかりませんでした。 ‘は明らかに網羅的なリストではありませんが、Zshのヘッドライン機能は’明らかであるはずなので、省略しましたか?ここで何が欠けていますか?
    • @CodyGray ‘わからないので、Appleは’習慣がありません自分自身を正当化する。状況が逆転した場合、’「優れたbash機能」セクションがないという事実と関係がある可能性があります。または、最後の非GPLv3bashが本当に古くなっているのに対し、zshはより寛大なライセンスを持っているためかもしれません。
    • 私の理解はライセンスが本質的に唯一の理由でした。 ‘は、macOSのbashがまだv3である理由でもあります。通りの言葉は、bashは更新されないということです’エンドユーザーがbrewなどを介してインストールしない限り、bashは削除されると予想されます。私の計画はに切り替えることでしたmacOSの場合はzshを遅くするよりも早くしますが、現時点ではDebianでbashを使用します。

    回答

    変更今すぐシェルをテストしてください。待つ必要はありません。

    chsh -s /bin/zsh 

    また、macOSユーザーの95%はコマンドラインを使用せず、使用するユーザーの95%は、重要な変更や変更を行う必要がないと推定しています。すべて。 (私は賭けます)シェルが存在することを知っている1%の10%は、.dotファイルに数行を移植する以外のことをする必要があります)

    プロンプトが変更されます。bashでプロンプトを変更した場合、zshでプロンプトを変更する方法は、難しくなく、文書化されています。 bash。

    新しいシェルは、主要なアイテムを壊したり、痛みを伴う適応期間を引き起こしたりした場合、地面から降りることができません。より根本的な変更が必要で、シェルについて考える必要があり、採用するためのトレーニングと意図が必要な場合は、を試してください。

    コメント

    • fishと競合しています。私は2年間使用していますが、一部のコピー/貼り付けされた1行の非互換性は疲れています。一方、これは非常に便利なシェルです(< kbd > Tab < / kbd >は素晴らしいです)
    • 魚を愛したかったのですが、それでも魚を愛したいのですが、10年の殻構造が多すぎますkshで、実際にそのフォールドを離れます。個人的には、喜んでbashを残し、zshを完全に受け入れます。
    • 私は魚に完全に圧倒されています。それは実際には、少しだけ雑然とした、もう1つのUnixライクなシェルです。 (文字通り”と書いてあります。最後に、ホームページにある90年代のコマンドラインシェル”です。)唯一の新しいシェル私は近年、実際に(主流の)テーブルに何か新しいものをもたらしたPowerShellを目にしました。これは、残念ながらWindowsに限定されすぎており、まだ.NETに限定されています。 PowerShellには、’まだ実行されていないそれほど新しいものはまだありません。 DCLまたはJCLで実行されますが、(ある程度)上品な方法で実行されています。
    • @bmikeでは、kshを使用しないのはなぜですか。 Appleは最新バージョンを出荷しています。私自身、私はずっと前にbashをパントしましたが、今zshを使い始める理由はありません。
    • この回答は’ bashとzshの違いをまったく説明していません。 …そして私は’なぜ” macOSユーザーの95%が’コマンドラインを使用しない”は、明らかにbashを使用しているユーザーの質問に関連しています。

    回答

    私のシェルスクリプトはそれほど複雑ではありません

    シェルスクリプトにshebang行がありますか(#! /bin/bashなどで始まります)?そうでない場合は、意図せずにbash機能を使用している可能性があります。この機能では、bashを使用してシバンなしでスクリプトを実行します。 dashやzshなどの他のシェルは、OSに任せ、通常は代わりに/bin/shを使用します。 macOSの/bin/shは、/bin/bashのコピーですが、を使用すると、動作が異なります。詳細は、Bashマニュアル、 6.11 BashPOSIXモードです。いくつかのポイント:

    1. Bashは、POSIXLY_CORRECT変数が設定されていることを確認します。

    この環境変数は、特にGNUツールがインストールされている場合、他の多くのツールの動作に影響を与える可能性があります。

    1. プロセス置換は使用できません。

    プロセス置換は<(...)または>(...)構文です。

    1. .およびsourceビルトインは、現在のディレクトリでファイル名を検索しませんPATHを検索しても見つからない場合は、引数。

    つまり、スクリプトが. fooを実行した場合現在のディレクトリにあるfooという名前のファイルをソースすることを期待しているため、機能しません。代わりに. ./fooを実行する必要があります。

    数値から推測できるように、POSIXモードでのbashの動作には多くの小さな違いがあります。スクリプトにbashを使用する場合は、シェバンを使用することをお勧めします。

    コメント

    • チェックすると、私が書いたシェルスクリプトの大部分のように見えますeまたは、シェバンで/ bin / bashを明示的に述べる(それらのごく一部)または/ bin / shを述べる(ほぼすべて)のいずれかを使用して、少なくとも問題にならないようにします。ありがとう。
    • プロセス置換が利用可能になったと思います。 Catalinaでもうまく試しました。参照: zsh.sourceforge.net/Intro/intro_7.html
    • @Siuは引き続き勝ちました’シェバンで/bin/shまたは/bin/bashを使用するヘルプスクリプト。 Zshはデフォルトのインタラクティブシェルにすぎません。’どこでもbashを置き換えることはできませんでした
    • @muruああ、わかりました。私は答えを注意深く読んでおらず、著者がプロセス置換について話しているのはzsh😅

    回答では利用できないと思いました

    物事をシンプルに保つという精神で…

    誰でも簡単で実用的なものを提供できますか比較、またはカタリナがリリースされたときに新しいシェルの準備に向けて作業を開始できるようにするために知っておく必要のある特定の障害ブロック?

    If新しいデフォルトのシェルを使用することを検討している場合は、次のことを検討してください。

    特定のパスは明確ではありませんがこれらの3つのアプローチにより、問題やソリューションスペースを過剰に設計することなく、十分な情報に基づいて決定を下すことができます。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です