web-dev-qa-db-ja.com

再帰的なmkdir

私が見落としているLinuxコマンドはありますか?それは次の行に沿って何かを行うことを可能にします:(疑似)

$ mkdir -R foo/bar/Zoo/andsoforth

または、ディレクトリを1つずつ作成する以外に方法はありませんか?

344
Dr.Dredel
$ mkdir -p foo/bar/Zoo/andsoforth
576
EEAA

mkdir -pを使用するは、最新のOSのほとんどにとって簡単な方法です。

mkdir -p foo/bar/Zoo/andsoforth

ただし、mkdir -pは多くのマニュアルで推奨されていません。 GNU makeおよびautoconfの使用に関する問題については、mkdir -pのドキュメントをご覧ください。

クロスプラットフォームのインストールおよび構成システムには、独自の安全なmkdir -pの代替案があります。

シェルコマンドラインで使用するCMake:

 cmake -E make_directory foo/bar/Zoo/andsoforth

Autoconfを前処理付きのスクリプトで使用:

AS_MKDIR_P(foo/bar/Zoo/andsoforth)

または:

AC_PROG_MKDIR_P(foo/bar/Zoo/andsoforth)

ただし、これらのソリューションでは、cmakeまたはautoconfM4)ツールをインストールする必要があります(および可能性のある前処理)。

install-shオプション付きの-dスクリプトも使用できます:

install-sh -d foo/bar/Zoo/andsoforth

このスクリプトは、autoconfおよびautomakeプロジェクトで使用されます。私はそれが最も安全な解決策であるに違いないと思います。

当時、私は依存関係のない標準/bin/shのクロスプラットフォームソリューションを探していましたが、見つかりませんでした。したがって、私は理想的ではないかもしれない次のスクリプトですが、ほとんどのクロスプラットフォーム要件に準拠していると思いますを書きました:

#! /bin/sh

cdirname() # cross platform alternative for 'dirname'
{
  # $1 - path
  test $# -eq 1 || { echo "Procedure 'cdirname' must have only one parameter. Scripting error."; exit 1; }
  echo "$1" | sed -n -e '1p' | sed  -e 's#//*#/#g' -e 's#\(.\)/$#\1#' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$#\1#' -
}

mkd() # cross platform alternative for 'mkdir -p'
{
  # $1 - directory to create
  test $# -eq 1 || { echo "Function 'mkd' can create only one directory (with it's parent directories)."; exit 1; }
  test -d "$1"  && return 0
  test -d "$(cdirname "$1")" || { mkd "$(cdirname "$1")" || return 1; }
  test -d "$1" || { mkdir "$1" || return 1; }
  return 0
}

このスクリプトは、mkdirのオプション-pが存在しない古いシステムで使用できます。

sedベースのクロスプラットフォームバージョンのdirnameがコードに追加されました。 dirnameと同様に機能します(パス/で正しいパス、ベース名のみのパス、末尾に/があるパス、末尾に\nsがあるパスとないパス)。この関数は、パスに現在のロケールで改行または無効な文字が含まれている場合は正しく機能しません。また、//////)の任意の組み合わせを単一の/に置き換えます

mkdir "$1" || return 1test -d "$1" || { mkdir "$1" || return 1; }に変更しました。パスが存在する場合、mkdirはエラーで終了し、このチェックはaaa\.のような構造を含むパスに必要です(aaaが存在する場合存在しない以前のバージョンはaaaを作成してから、もう一度作成しようとします)。

このバージョンのmkdは、パスがすでに存在する場合でもエラーを生成しません(ただし、並列実行でそのようなエラーを生成する可能性があります)。コマンドラインでいくつかのディレクトリを取得できません。

オプション-p inコマンドmkdirは、必要に応じてp arentディレクトリを作成します(既存の場合はエラーなし):

mkdir -p foo/bar/Zoo/andsoforth

別の方法は、たとえば&&(指定したフォルダーが存在する場合はエラー):

mkdir foo && mkdir foo/bar && mkdir foo/bar/Zoo && mkdir foo/bar/Zoo/andsoforth

連鎖演算子&&は、前のコマンドがエラーなしで終了した場合にのみ次のコマンドが実行されるように、コマンドをチェーンするために使用されます。

もちろん、最初の方法の方が優れています。

0
simhumileco