ネストされたディレクトリの作成を可能にするために、mkdirにデフォルトで-pフラグが設定されていないのはなぜですか?


11

-pフラグをmkdirデフォルトで設定しない理由はわかりません。

  -p, --parents     no error if existing, make parent directories as needed

それは私が見ることができるものからの非破壊的なコマンドです。これが機能する方法について重要な何かを見逃しましたか?

次に、これをデフォルトの動作にする簡単な方法はありますmkdirか?


2
これを.bashrc:に入れてくださいalias mkdir="mkdir -p"
ケビン

すべての議論の後、私は次のエイリアスを使用することを決定しましたmkdp
Treffynnon

回答:


6

これはオプションの機能であり、特にスクリプトでは常に望ましいとは限りません。スクリプトの場合は、次の欠点を考慮してください。

  • ディレクトリがすでに存在しているという事実は報告されていません。スクリプトが新しく作成されたディレクトリにいくつかのファイルを置くことになっていて、そのディレクトリがすでに存在しファイルを含んでいる場合、スクリプトは多くの混乱を引き起こす可能性があります。(後でスクリプトによってそこに配置されたファイルをフィルターで除外するのは面倒です。)
  • 上記の裏側では、一部のスクリプト(またはその一部)は、以前に(おそらく他のパッケージ/スクリプトによって)作成されたディレクトリ構造に依存している場合があります。たとえば、パッケージインストールスクリプトでは、サブディレクトリにライブラリを配置する必要があるかもしれません/usr/local/lib/GreatSoftware/ImportantPartOfItが、ライブラリは/の下にあるものへの/リンクに依存しています/usr/local/lib/GreatSoftware。これがない場合、スクリプトは続行されません。

の一般的な動作はmkdir、そのような状況が報告され、すぐに捕捉できるため、簡単かつ自然になります。


mkdir -pシェルで常に使用する場合は、エイリアスを作成できます。

alias mkdir='mkdir -p'

(これは.bashrc、シェルが使用する構成または任意の構成に移動する必要があります。)


1
非標準的な方法で動作させるために、標準コマンドにエイリアスを付けることはお勧めしません。それはスクリプトを移植不可能にし、読者を混乱させるかもしれません。新しいエイリアスまたは関数を作成するalias mkdp="mkdir -p"ことをお勧めします。
jlliagre 2011年

2
@jlliagreいいえ、スクリプトには影響しません。でローカルに定義されたエイリアス.bashrcは、(通常)環境に影響を与えません。
rozcietrzewiacz 2011年

確かに、あなたは私のポイントを逃した。自分で使用する場合でも、動作を変更するために標準コマンドにエイリアスを設定することはお勧めできません。最悪の例はユビキタスalias rm='rm -i'です。
jlliagre 2011年

1
@jlliagre誰にも勧められませんか?;)しかし、はい、私は同意します。私自身は別のエイリアスを使用したいのですが、実用的な理由からではなく、イデオロギー上の理由からです。私はまた、rm -iエイリアスが常に悪いとは思いません-悪い習慣につながるかもしれません。確かにないすべてのコマンドエイリアスは、同様に良い/悪いです-考えるls="ls --color=auto"か、ssh="TERM=xterm ssh"例えば。
rozcietrzewiacz 2011年

私の推薦にはイデオロギーはありません。rmエイリアスは、多くの失われたファイルの間接的な原因です(このエイリアスの犠牲者はたくさんいます)。mkdirの方が、はるかに少ない範囲で、不要な副作用があると疑っていました。もちろん、私はあなたのsshやlsの例のように、見かけ上の、行動的な、変更に反対しているわけではありません。
jlliagre 2011年

16

もちろん、親ディレクトリの作成をデフォルトにすべきだと主張することもできます。親が存在しない場合、いくつかのチェックオプションを使用してディレクトリの作成を防ぐことができます。

しかし、それが逆になっている理由は単なる歴史です。mkdirの基本バージョンでは、親ディレクトリは作成されませんでした。これが、X11ディストリビューションに、このタスクを実行できるmkdirhierというコマンドが付属している理由です。親ディレクトリが存在するかどうかを確認し、必要に応じて作成します。

後でこの機能が多くのUNIXバージョンのコマンドmkdirに追加されました(最近のPOSIX標準にあるかどうかはわかりません)。互換性を維持するために、この機能はオプションフラグをオンにすることで利用できるようになりました-p

デフォルトでオンにするのが悪いのはなぜですか?親ディレクトリが存在しない場合、スクリプトはmkdirの失敗に依存する場合があります。特にユーザーrootとして、デフォルトでディレクトリツリーを作成するのは危険な場合があります。

例:

 if mkdir /backup/$(uname -n)/$(date +%Y%m%d)
  then
    perform_backup ...

この例では、ディレクトリが作成され、ファイルシステム/backupがマウントされていなくてもバックアップが実行され/backup/$(uname -n)、デフォルトが逆の場合、親は存在しません。

経験則:ツールのデフォルトの動作を変更しないことをお勧めします。必要に応じて、デフォルトの動作を変更できるオプションを提供します。


2
ここで使用したマウントの例が好きです。その特定のシナリオについては考えていませんでした。
Treffynnon、2011年

1
-p(および-m)オプションは、1983年にSystem Vによって導入されました。どちらも間違いなくPOSIX標準の一部です。
jlliagre 2011年

4

これはちょっと哲学だと思います。ベアmkdir(1)コマンド(オプションなし)はmkdir(2)システムコールを表し、シェルでその機能を提供し、多かれ少なかれ何もしません。


4

始まり、唯一の裸があったmkdirコマンド。Unixの設計原則に従って、この単純なコマンドは、ディレクトリの作成という1つの単純なタスクを実行しました。

後で、特定のパスが存在することを確認するために呼び出し元がゼロ、1つ、または複数のディレクトリを作成したいという一般的な使用例を処理mkdirする-pオプションを取得しました。これは、いくつかの理由でデフォルトの操作にはなりませんでした。まず、すべてのシステムがこのより複雑な機能を備えているわけではなく、-pオプションを必要とすることは、それを使用するスクリプトがmkdir: invalid option -z不規則にディレクトリの作成に失敗するのではなく、合理的なエラーメッセージ(など)を受け取ることを意味しました。第2に、そして最も重要なこととして、の動作mkdir -pmkdir、すべての場合において互換性のある代替ではありません。

特に、ほとんどのファイルシステムでmkdirは、アトミック操作です。プログラムが実行さmkdir playgroundれ、コマンドが成功した場合、プログラムはplaygroundディレクトリを作成したことを認識しています。これにより、プログラムは新しいディレクトリを専用の遊び場として扱うことmkdir playgroundができます。同じプログラムの別のインスタンスが同時に実行されている場合、への呼び出しは失敗します。このプロパティはmkdir -p、引数の存在を許可するため、明らかに提供されていません。

mkdir -p最初から存在していた場合はmkdir -a、単一ディレクトリ作成コマンドのようなもので、それをデフォルトモードにすることができます。しかし、それは通常のUnix設計哲学には従わなかったでしょう。ほとんどの基本的なユーティリティは、基礎となるプリミティブの単純なラッパーであり、手の込んだオプション(複数のディレクトリを一度に作成するなど)を備えています。


2

私にとっての問題は、デフォルトの場合の-pオプションの動作が本質的に副作用であることです。それはあなたがそれをするように頼んだことに追加の何かをすることによってコマンドに複雑さを追加します。覚えておくべきもう一つの目に見えないものです。サウンドプログラミングの基本的なルールの1つは、副作用を回避することです。

最新のプログラミング言語は非常に強力であるため、言語が提供するプリミティブから必要な複雑なコマンドを比較的簡単に作成できます。そのためには、どのような行動が必要かについて意識的に決定する必要があり、何が行われたかについて具体的で目に見える記録が残ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.