Bashシェルスクリプトにディレクトリが存在するかどうかを確認するにはどうすればよいですか?


回答:


5150

シェルスクリプトにディレクトリが存在するかどうかを確認するには、以下を使用できます。

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

または、ディレクトリが存在しないかどうかを確認するには:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

ただし、Jon Ericsonが指摘しているように、ディレクトリへのシンボリックリンクもこのチェックに合格することを考慮に入れないと、後続のコマンドが意図したとおりに機能しない可能性があります。例えばこれを実行します:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

エラーメッセージが表示されます。

rmdir: failed to remove `symlink': Not a directory

したがって、後続のコマンドがディレクトリを想定している場合は、シンボリックリンクを別の方法で処理する必要があります。

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

変数をラップするために使用される二重引用符に特に注意してください。この理由については、8jean が別の回答で説明しています

変数にスペースやその他の異常な文字が含まれていると、スクリプトが失敗する可能性があります。


29
GNUツールで安全にプレイしたい場合--は、使用を強くお勧めします(オプション終了マーカー)。それ以外の場合、変数にオプションのように見えるものが含まれていると、スクリプトはスペースと同様に失敗します。
マルク・ムッツ-mmutz 2009

2
最新バージョンのbash、kshなどの場合、[...]は組み込みです
fpmurphy

79
心に留めておくべき一つのことは:[ ! -d "$DIRECTORY" ]いずれかの場合にtrueになります$DIRECTORYが存在しない場合、またはありませんが存在しますがディレクトリではありません。のようなものを考えてくださいif [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi"$DIRECTORY"ファイルの場合、これは失敗します。(もちろん、mkdir成功したかどうかを確認する必要があります。失敗する理由はいくつかあります。)
キース・トンプソン

5
チェックが実行されるとすぐに、他のプロセスのために状況がすでに変化している可能性があることに言及する価値があるかもしれません。多くの場合、ディレクトリを作成または使用して、障害に対処する方が適切です。
Alfe、

12
ディレクトリ(-d)とシンボリックリンク(-L)の両方をテストする代わりに、のように変数にスラッシュを追加する方が簡単if [ -d "${THING:+$THING/}" ]です。ディレクトリは余分なスラッシュを気にしません。ファイルはfalseと評価されます。空は空のままなので、false。そして、シンボリックリンクはその宛先に解決されます。もちろん、それはあなたの目標次第です。あなたがそこに行きたいなら、これは大丈夫です。それ削除したい場合は、この回答のコードの方が優れています。
ghoti

531

Bashスクリプトで変数を参照するときは、常に変数を二重引用符で囲むことを忘れないでください。最近の子供たちは、ディレクトリ名にスペースや他の多くの面白い文字を含めることができるという考えで成長しました。(スペース!昔、空想的なスペースはありませんでした!;))

ある日、子供たちの1人が$DIRECTORYsetを使用"My M0viez"してスクリプトを実行し、スクリプトが爆発します。あなたはそれを望まない。これを使用してください。

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

9
二重引用符を使用するもう1つの理由は、$ DIRECTORYが何らかの理由で設定されていない場合です。
ジョンエリクソン

2
「変数は常に二重引用符で囲みます... bashスクリプトで」bashの場合、[[...]]を使用する場合、技術的には不要です。tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETSを参照してください(注:単語の分割はありません):「[[と]]の間でファイル名の展開や単語の分割は行われませんが、パラメーターの展開とコマンドの置換は行われます。」
マイケル2014

2
Unix / Linuxのディレクトリには空白を入れないでください。その後、スクリプトをそれに適合させないでください。Windowsがそれをサポートするのは十分に悪いですが、Windowsスクリプトにすべての影響がありますが、何が好きでも、不必要な要件を導入する必要はありません。
tvCa 2014

18
@tvCaユーザーは一般的に、開発者にとって物事を容易にすることを強いられるよりも、ディレクトリ名をより柔軟に許可することを好みます。(実際、長いファイル名を扱う場合、私が過去にスクリプトやプログラムでスペースを含むパスを考慮していなかったために苦しんでいたとしても、スペースのないファイルは単語の折り返しを殺すので苦痛です。)
JAB

2
ハ。スペースは、通常はグリフを持たない単なる文字です。とにかく、バックスラッシュでエスケープできます。
uchuugaka

228

-dテストは驚くべき結果をもたらす可能性があることに注意してください。

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

下のファイル:「ディレクトリはディレクトリではない場合」答え:「ディレクトリへのシンボリックリンクの場合」もう少し徹底的なテスト:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

詳細については、BashマニュアルのBash条件式[組み込みコマンド、および[[複合コマンドください


12
または、ディレクトリでのみ作業する必要があると想定します(リンクは無視できます)=> if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi...または、リンクとディレクトリの両方で機能する1つのコマンド:rm -r tmpdir
michael

218

二重括弧バージョンを使用testすると、論理テストをより自然に記述できます。

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

以下のためにif [[ -d "$TARFILE" ]]私は[[取得しています:見つからない
TheVillageIdiot

15
@TheVillageIdiotと@ Hedgehog、bashシェルを使用していますか?二重ブラケットは普遍的にサポートされていません。ここでは、その時点でのSOの答えがあります:stackoverflow.com/questions/669452/...
yukondude

6
また、Busyboxでは、デフォルトのコンパイルオプションを備えたash [[ ]]がサポートされていますが、実際にはに別の機能を提供していません[ ]。移植性が懸念される場合は[ ]、必要な回避策をそのまま使用します。
dubiousjim

6
...シェルスクリプトでbashコンストラクトを使用する場合、スクリプトの最初の行は#!/ bin / bash(および#!/ bin / sh、kshなどではない)
michael

bashで二重角括弧を使用する場合、変数を引用符で囲む必要はありません。
Hubert Grzeskowiak 2017

157

短い形式:

[ -d "$DIR" ] && echo "Yes"

6
これは次のように機能します if $dir is a dir, then echo "yes"か?少し説明すると役立つでしょう:)
Martijn

5
cmd && otherは一般的な省略形です。if cmd; then other; fiこれはブール論理をサポートするほとんどのプログラミング言語で機能し、短絡評価と呼ばれます。
Tripleee 2016年

1
動作は同じではありませんset -e(これはシェルプログラミングのベストプラクティスです)。
ドルメン

1
@dolmen [ -d "$DIR" ]はチェックされる(が続く&& echo Yes)のでset -e、スクリプトの動作に違いはないと思います(つまり、テストが失敗した場合、スクリプトは正常に続行します)。
tzot

132

ディレクトリが存在するかどうかを確認するには、次のifような単純な構造を使用できます。

if [ -d directory/path to a directory ] ; then
# Things to do

else #if needed #also: elif [new condition]
# Things to do
fi

ネガティブでそれを行うこともできます:

if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory

:注意してください。開始と終了の両方のブレースの両側に空白を残します。

同じ構文で使用できます:

-e: any kind of archive

-f: file

-h: symbolic link

-r: readable file

-w: writable file

-x: executable file

-s: file size greater than zero

これは、ファイルスイッチで話題から外れることを除いて、2008年に承認された回答よりもどのように優れていますか?
Dan Dascalescu

[!-dディレクトリ/ディレクトリへのパス]
user1855805

108
  1. ディレクトリまたはファイルが存在するかどうかをテストする簡単なスクリプト:

    if [ -d /home/ram/dir ]   # For file "if [-f /home/rama/file]"
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
  2. ディレクトリが存在するかどうかを確認する簡単なスクリプト:

    mkdir tempdir   # If you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi

    上記のスクリプトは、ディレクトリが存在するかどうかを確認します

    $? 最後のコマンドが成功した場合は「0」を返し、それ以外の場合はゼロ以外の値を返します。仮定しtempdir、既に存在しています。次にmkdir tempdir、以下のようなエラーが発生します。

    mkdir:ディレクトリ 'tempdir'を作成できません:ファイルが存在します


4
最初のディレクトリが存在しない場合は、2番目のディレクトリがディレクトリを作成します。その場合、それはべき等ではありません。
Shihe Zhang

👆👆👆。2つ目は危険そうです。それはディレクトリを作成するので、dirが存在しないことはもはや真実ではありません。
クリス

92

使用できますtest -d(を参照man test)。

-d file ファイルが存在し、それがディレクトリであれば真。

例えば:

test -d "/etc" && echo Exists || echo Does not exist

注:testコマンドは条件式と同じ[(参照man [:)なので、シェルスクリプト間で移植できます。

[-これはtest組み込みの同義語ですが、最後の引数は、開始と]一致するようにリテラルでなければなりません[

可能なオプションまたは詳細なヘルプについては、以下を確認してください。

  • help [
  • help test
  • man test または man [

55

または完全に役に立たないもののために:

[ -d . ] || echo "No"

6
「いいえ」は印刷されません。別のスレッドまたは他の方法で削除されない限り、現在のディレクトリは常に存在します。
Jahid 2015

完全なサンプル:)受け入れられた回答と比較していくつかの回答が「ユニーク」であることを考えると
Sergey Sargsyan

4
なぜこれが何度も賛成されているのですか?質問の答えにはなりません。
codeforester 2018年

ITがベストアンサーEVAであるため
Karl Morrison

52

非常に実用的なイディオムを次に示します。

(cd $dir) || return # Is this a directory,
                    # and do we have access?

私は通常それを関数にラップします:

can_use_as_dir() {
    (cd ${1:?pathname expected}) || return
}

または:

assert_dir_access() {
    (cd ${1:?pathname expected}) || exit
}

このアプローチの良い点は、適切なエラーメッセージを考える必要がないことです。

cd標準エラーへの標準的な1行のメッセージが既に表示されます。また、私が提供できる以上の情報を提供します。cdサブシェル内で実行することにより( ... )、コマンドは呼び出し元の現在のディレクトリに影響を与えません。ディレクトリが存在する場合、このサブシェルと関数は何もしません。

次に渡す引数は次のcdとおり${1:?pathname expected}です。これは、以下でより詳細に説明する、より複雑な形式のパラメーター置換です。

Tl; dr:この関数に渡された文字列が空の場合、サブシェルを再び終了( ... )し、指定されたエラーメッセージで関数から戻ります。


ksh93manページからの引用:

${parameter:?word}

parameter が設定され、null以外の場合 は、その値を置き換えます。それ以外の場合は、印刷wordしてシェルを終了します(対話型でない場合)。もしword省略された標準メッセージがプリントされます。

そして

コロンなら :上記の式からが省略されているシェルはパラメーターが設定されているかどうかのみをチェックします。

ここでの表現は、次のように、シェルのドキュメントに固有のものです。 word、空白を含む任意の適切な文字列を指す場合があるです。

この特定のケースでは、標準エラーメッセージが 1: parameter not setでは不十分であることので、ここで想定している値のタイプにズームインします。pathnameディレクトリます。

哲学ノート:

シェルはオブジェクト指向言語ではないので、メッセージにはpathname、ではなく、と書かれていdirectoryます。このレベルでは、私はそれを単純に保ちたいです-関数への引数は単なる文字列です。


これは、存在を確認するだけではありません。ユーザーレベルでのアクセシビリティを確認します。SO質問は存在のみを表します。だから正しい答えはtest -d@Grundlefleckが説明したとおりです。
F.ハウリ

7
@ F.Hauri-彼はそれ以上何も要求しなかった、それは本当です。ただし、通常はそれ以上のことを知る必要があることがわかりました。
Henk Langeveld

そして、それがrootとして実行されない限り、テストが決定的なものになることはあり得ませんでした。 test -d /unreadable/exists引数が存在していても失敗します。
Henk Langeveld

36
if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

上記のコードは、ディレクトリが存在するかどうか、および書き込み可能かどうかをチェックします。


1
-aは実質的に-eと同じです。「非推奨」であり、その使用は推奨されません。
CousinCocaine 2014年

27
DIRECTORY=/tmp

if [ -d "$DIRECTORY" ]; then
    echo "Exists"
fi

オンラインで試す


-> [`` -dのspace後の覚え書き。スペースがないためにエラーが発生しました[
Raj

4
再び、この答えはすでに2008年に与えられており、より有用な説明があります。ここで唯一新しいのは、オンラインの遊び場です。
Dan Dascalescu

24

Bashプロンプトで次のコードを入力します。

if [ -d "$DIRECTORY" ]; then
    # If true this block of code will execute
fi

再び、この答えはすでに2008年に与えられました。それを繰り返すことの意味は何ですか?!
Dan Dascalescu

21

使用するその他の機能 find

  • サブディレクトリ内のフォルダの存在を確認します。

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
  • 現在のディレクトリ内のパターンに基づいて、1つまたは複数のフォルダーの存在を確認します。

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
  • 両方の組み合わせ。次の例では、現在のディレクトリにフォルダーが存在するかどうかを確認します。

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi

こんにちはニール。次のようなパターンによっては、ディレクトリの存在を確認するのに役立つかもしれませんfind -maxdepth 1 -type d -name 'pattern'。私はあなたの答えにこのトリックを追加してもよろしいですか?乾杯;)
olibre 2013年

20

実際には、防弾アプローチを得るためにいくつかのツールを使用する必要があります。

DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # Now you're testing
    echo "It's a dir";
fi

を使用している限り、スペースや特殊文字を気にする必要はありません"${}"

[[]]などの携帯型としてではない[]が、ほとんどの人は(すべての後、ほとんどの人は、コマンドライン:-Pでも、仕事をしないので)バッシュの最近のバージョンで動作するので、利益が悩みよりも大きくなります。


17

if飛躍する前に見るのではなく、やりたいことを何でもすることを考えましたか?

つまり、入力する前にディレクトリの存在を確認する場合は、次のようにします。

if pushd /path/you/want/to/enter; then
    # Commands you want to run in this directory
    popd
fi

指定したパスがpushd存在する場合は、そのパスを入力するとで終了します。0つまりthen、ステートメントの一部が実行されます。存在しない場合は、何も起こりません(ディレクトリが存在しないことを示す出力がある場合を除き、これはおそらくデバッグに役立つ副作用です)。

これは自分自身を繰り返す必要があるこれよりも良いようです:

if [ -d /path/you/want/to/enter ]; then
    pushd /path/you/want/to/enter
    # Commands you want to run in this directory
    popd
fi

同じことはで動作するcdmvrmあなたが存在しないファイルでそれらをしようとした場合、彼らはエラーで終了し、それが存在しない旨のメッセージを印刷し、あなたのよ...、などthenのブロックはスキップされます。存在するファイルでそれらを試すと、コマンドが実行され、ステータスで終了し、ブロックを実行0できますthen


2
pushdは、これを行う最もエレガントな方法です。回答として投稿しようとしていました:)
melMass





11

この答えはシェルスクリプトとしてまとめました

$ is_dir ~                           
YES

$ is_dir /tmp                        
YES

$ is_dir ~/bin                       
YES

$ mkdir '/tmp/test me'

$ is_dir '/tmp/test me'
YES

$ is_dir /asdf/asdf                  
NO

# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
  echo "Folder doesnt exist: $DIR";
  exit;
fi

is_dir

function show_help()
{
  IT=$(CAT <<EOF

  usage: DIR
  output: YES or NO, depending on whether or not the directory exists.

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

DIR=$1
if [ -d $DIR ]; then 
   echo "YES";
   exit;
fi
echo "NO";

10

-eチェックを使用すると、ファイルがチェックされます。これにはディレクトリも含まれます。

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi

1
そして、OPの質問に正しく答えません-それはディレクトリですか?
マークスチュワート

8

あたりとしてジョナサンさんのコメント:

ディレクトリを作成したいが、それがまだ存在しない場合、最も簡単な方法はmkdir -p、ディレクトリを作成することと、パスの上の欠落しているディレクトリを使用することであり、ディレクトリがすでに存在する場合でも失敗しないので、すべてを行うことができます。一度に:

mkdir -p /some/directory/you/want/to/exist || exit 1

7
if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

これは完全に真実ではありません...

そのディレクトリに移動する場合は、そのディレクトリに対する実行権限も必要です。多分あなたも同様に書き込み権限を持っている必要があります。

したがって:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi

if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

7

fileプログラムを使用します。Linuxではすべてのディレクトリもファイルであるため、次のコマンドを発行するだけで十分です。

file $directory_name

存在しないファイルを確認する: file blah

出力: cannot open 'blah' (No such file or directory)

既存のディレクトリを確認する: file bluh

出力: bluh: directory


1
いいアイデアですが、どちらの場合も、ファイルコマンドは常に0の終了コードを返します。また、ファイル/ディレクトリが見つからない場合:(。
danger89

6

このlsコマンドと-l(長いリスト)オプションを組み合わせて使用すると、ファイルとディレクトリに関する属性情報が返されます。
特に、ls -l出力の最初の文字は通常a dまたはa -(ダッシュ)です。以下の場合にはd記載されているかわからためのディレクトリです。

次の1行のコマンドは、指定さISDIRれた変数にディレクトリへのパスが含まれているかどうかを示します。

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

実用的な使い方:

    [claudio@nowhere ~]$ ISDIR="$HOME/Music" 
    [claudio@nowhere ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [claudio@nowhere ~]$ touch "empty file.txt"
    [claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt" 
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory

+1ですが、ISDIRがまったく存在しない場合、エラーメッセージと診断メッセージが表示されます。
ysap


5

実際のディレクトリかシンボリックリンクかに関係なく、ディレクトリが存在するかどうかを確認する場合は、次のようにします。

ls $DIR
if [ $? != 0 ]; then
        echo "Directory $DIR already exists!"
        exit 1;
fi
echo "Directory $DIR does not exist..."

説明:「ls」コマンドは、ディレクトリーまたはシンボリック・リンクが存在しない場合、エラー「ls:/ x:No such file or directory」を出し、「$?」を介して取得できる戻りコードをnonに設定します-null(通常は "1")。「ls」を呼び出した直後に、必ず戻りコードを確認してください。


3
:別の方法としては、この短いバージョンを使用することができますif ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
derFunk

5

(1)

[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"

(2)

[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"

(3)

[[ -d run_dir  && ! -L run_dir ]] && echo Exists || echo "Not Exists"

上記のいずれかの方法で問題が見つかった場合:

lsコマンド; ディレクトリが存在しない場合-エラーメッセージが表示されます

[[ `ls -ld SAMPLE_DIR| grep ^d | wc -l` -eq 1 ]] && echo exists || not exists

-ksh:not:not found [該当するファイルまたはディレクトリはありません]


「上記」とは何を指しますか?この回答または以前の回答の3つのコマンドライン?(ここのコメントではなく、回答を編集して返信してください。よろしくお願いします。)
Peter Mortensen

4

すばらしい解決策はたくさんありますが、適切なディレクトリにいないと、最終的にすべてのスクリプトが失敗します。したがって、次のようなコード:

if [ -d "$LINK_OR_DIR" ]; then
if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here
    rm "$LINK_OR_DIR"
else
    # It's a directory!
    # Directory command goes here
    rmdir "$LINK_OR_DIR"
fi
fi

実行時に、たまたま確認したサブディレクトリがあるディレクトリにいる場合にのみ、正常に実行されます。

私はこのような最初の質問を理解しています。ファイルシステム内のユーザーの位置に関係なく、ディレクトリが存在するかどうかを確認することです。したがって、コマンド 'find'を使用するとうまくいく場合があります。

dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d

このソリューションは、ファイル/ディレクトリを検索するときに便利な機能であるワイルドカードを使用できるため、優れています。唯一の問題は、検索されたディレクトリが存在しない場合、「find」コマンドは標準出力に何も出力せず(私の好みのためのエレガントなソリューションではありません)、それにもかかわらずゼロの出口があります。たぶん誰かがこれを改善できるでしょう。


13
現在の作業ディレクトリを丁寧に調べたり、指定した絶対パスを使用したりするのではなく、プログラムがハードドライブ全体を調べてディレクトリを見つけた場合は、気分が悪くなります。あなたが提案したものは、名前locateが付けられたツールには良いかもしれませんが、他には何もいいわけではないかもしれません...
サーノルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.