カタリナがデフォルトでBashではなくZshに設定されるというニュースで切り替えについて多くの結果が見つかり、シェルスクリプトで問題が発生する可能性がありますが、私はZshに精通していないため、これらの問題が何であるかを知ることができません。
私のシェルスクリプトは実際にはそうではありません。複雑ですが、私はmacOSとLinuxでBashを使用したことがあります。Zshの使用経験はありません。簡単な実用的な比較や、知っておく必要のある特定の障害を誰かが提供できるので、準備に向けて作業を開始できます。 Catalinaがリリースされたときの新しいシェル?
コメント
システム上の”重要な”については?
回答
まず、いくつかの重要なこと:
- bashは消えません。すでにbashを使用している場合は、何も変わりません。変更点は、zshが new アカウントのデフォルトのログインシェルになることだけです。それでも、代わりにbashを選択できます。
- スクリプトは影響を受けません。変更されるのは、インタラクティブに使用するためのシェル、つまり端末のシェル(および、crontabなどのログインシェルを使用する他のいくつかのもの)です。
#!/bin/bash
やivなどのシバン行で始まる実行権限を持つスクリプトがファイルにある場合id = “2a6c845d50”>
または#!/usr/bin/env bash
の場合、以前とまったく同じように機能し続けます。
ここで、切り替えを検討していると仮定します。何年にもわたって可能性があったzshに対して、これが遭遇する主な違いです。これは完全なリストではありません!
インタラクティブな使用の主な違い
構成ファイル: bash読み取り(主に).bashrc
非ログインインタラクティブシェル(ただし、macOSはデフォルトでターミナルでログインシェルを開始します)、.profile
または、および.inputrc
。 Zsh読み取り(主に).zshrc
(すべてのインタラクティブシェル内)および.zprofile
(ログインシェル内)。つまり、bashのカスタマイズは適用されません。「移植する必要があります。多くの調整が必要になるため、ファイルをコピーするだけでは不十分です。
キーバインディングは完全に異なる構文を使用します。 Bashは、 .inputrc
とbind
組み込みを使用してキーを readlineコマンド。 Zshは、 bindkey
ビルトインを使用して、キーを zleウィジェットにバインドします。ほとんどのreadlineコマンドにはzshに相当するものがありますが、必ずしも完全に同等であるとは限りません。
キーバインディングについて言えば、Vi(m)をターミナル内エディターとして使用し、シェルのコマンドラインモードとしては使用しない場合、
またはVISUAL
はvi
または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つのメカニズムがあります。
- 忘れることができる
compctl
の「古い」完了メカニズム。 -
compadd
およびアンダースコアで始まる多くの関数を使用した「新しい」完了メカニズムおよび強力で複雑なユーザー構成メカニズム。 - へのエミュレーション
bashcompinit
を実行して有効にできるbash完了機能をサポートします。エミュレーションは100%完全ではありませんが、通常は機能します。
多くのbashの shopt
設定には対応するがありますsetopt
inzsh。
Zsh doe sn “t #
は、スクリプト(.zshrc
などを含む)でのみ、デフォルトでコマンドラインのコメント開始として扱います。インタラクティブなコメントを有効にするには、 setopt interactive_comments
を実行します。
スクリプトの主な違い
(そしてもちろんコマンドラインのパワーユーザーの場合)
bashでは、$foo
はfoo
は、空白文字で分割し、空白で区切られた部分ごとに、ワイルドカード文字が含まれていて既存のファイルと一致する場合は、パターンを一致リストに置き換えます。 foo
の値を取得するには、"$foo"
が必要です。同じことがコマンド置換$(foo)
にも当てはまります。 zshでは、$foo
はfoo
の値であり、$(foo)
は
は、2つの例外を除いて、最後の改行を差し引いたものです。引用符で囲まれていない空の変数を展開したために単語が空になった場合、その単語は削除されます(たとえば、a=; b=; printf "%s\n" one "$a$b" three $a$b five
はone
、空の行、
、five
)。引用符で囲まれていないコマンド置換の結果は空白で分割されますが、ワイルドカードマッチングは行われません。
Bash 配列には、0から(長さ-1)までのインデックスが付けられます。 Zsh配列には、1から長さまでのインデックスが付けられます。 a=(one two three)
の場合、bashでは${a[1]}
はtwo
ですが、zshでは「 one
。bashでは、中括弧なしで配列変数を参照するだけで、最初の要素を取得します。たとえば、$a
はone
および$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.txt
、qux.txt
として展開されます。 -
foo/bar/*(.:r)
:foo/bar
の下にある通常のファイルを取得し、拡張子を削除します。例えば。foo/bar/qux.txt
はfoo/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.jpg
がimage10.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
-
bash
構文は引き続きbashを見つけて呼び出します。 - Mojaveからの同じbashがCatalinaで出荷されており、移行されたユーザーは古いシェルを保持します。
- 多くのブログには、設定ファイルの移動に関する優れた記事があります-これがそのようなものです- https://scriptingosx.com/2019/06/moving-to-zsh-part-2-configuration-files/
- Arminは、彼のブログシリーズを約22,000語の適切な本に変えました。
また、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モードです。いくつかのポイント:
- Bashは、
POSIXLY_CORRECT
変数が設定されていることを確認します。
この環境変数は、特にGNUツールがインストールされている場合、他の多くのツールの動作に影響を与える可能性があります。
- プロセス置換は使用できません。
プロセス置換は<(...)
または>(...)
構文です。
.
および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新しいデフォルトのシェルを使用することを検討している場合は、次のことを検討してください。
- Zshに回転を与え、マシンのシェル設定を変更せずにいくつかの違いを感じしたい場合Dockerコンテナで Powerline10kを試して、それがお茶かどうかを確認するかもしれません。
- すべてのベルが必要ない場合は口笛を吹いて、基本的なスクリプトだけにBashを使用する」他の人が説明しているように、シェルを設定するのはかなり簡単です。 Bash5の機能を使用したいそれは「かなり macOSの簡単なアップグレードです。 li>
- スクリプトの移植性を改善して、「両方のシェルで期待どおりに機能する可能性が高くなるようにする場合は、 POSIX準拠をテストしますそして「bashisms」を削除します。私はこれに ShellCheck を使用しましたが、それほど複雑でないスクリプトでは非常にうまく機能します。
特定のパスは明確ではありませんがこれらの3つのアプローチにより、問題やソリューションスペースを過剰に設計することなく、十分な情報に基づいて決定を下すことができます。
bash version 3.2.57(1)
を使用している:Appleがbash version 3.2.57(1)
を使用しているかどうか知っていますかdiv id = “6eb5ca1147”>