4107

Bashシェルスクリプト内で、ディレクトリが存在するかどうかを確認するために使用できるコマンドは何ですか?

4

35 に答える 35

5558

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

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 によって説明されています。

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

于 2008-09-12T20:07:06.113 に答える
580

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

ある日、それらの子供の 1 人がスクリプトを$DIRECTORYset で実行し"My M0viez"、スクリプトが失敗します。あなたはそれを望んでいません。だからこれを使う。

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi
于 2008-09-15T22:00:49.730 に答える
252

-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のマニュアルを参照してください。

于 2008-09-12T20:26:04.803 に答える
234

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

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi
于 2008-09-12T21:33:08.963 に答える
206

短縮形:

# if $DIR is a directory, then print yes
[ -d "$DIR" ] && echo "Yes"
于 2008-09-12T21:08:48.977 に答える
144

ディレクトリが存在するかどうかを確認するには、次の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
于 2015-04-08T02:50:09.670 に答える
107

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

-d file ファイルが存在し、ディレクトリである場合は true。

例えば:

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

注: このコマンドは条件式(参照: )testと同じであるため、シェル スクリプト間で移植可能です。[man [

[- これはビルトインのシノニムですtestが、最後の引数はリテラル]でなければならず、開始と一致し[ます。

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

  • help [
  • help test
  • man testまたman [
于 2015-09-12T21:25:05.697 に答える
60

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

[ -d . ] || echo "No"
于 2009-08-17T14:02:43.420 に答える
59

これは非常に実用的なイディオムです:

(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: この関数に渡された文字列が空の場合、再びサブシェル( ... )を終了し、指定されたエラー メッセージとともに関数から戻ります。


ksh93マニュアルページから引用:

${parameter:?word}

が設定されていて null でない場合 parameter は、その値を置き換えます。それ以外の場合は、出力wordしてシェルを終了します (対話的でない場合)。を省略するwordと、標準のメッセージが出力されます。

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

ここでの言い回しは、シェルのドキュメントに特有のものであり、word空白を含む適切な文字列を指す場合があります。

この特定のケースでは、標準のエラー メッセージ1: parameter not setでは不十分であることがわかっているので、ここで期待される値のタイプ、つまりpathnameディレクトリのタイプを拡大します。

哲学的なメモ:

シェルはオブジェクト指向言語ではないため、メッセージにはpathnameではなくと表示されますdirectory。このレベルでは、むしろシンプルに保ちたいと思います。関数への引数は単なる文字列です。

于 2012-08-09T21:43:52.137 に答える
41
if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

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

于 2010-04-21T06:06:05.000 に答える
32

を使用したその他の機能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
    
于 2008-09-12T20:17:12.577 に答える
27

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

if [ -d "$DIRECTORY" ]; then
    # If true this block of code will execute
fi
于 2014-11-05T03:39:01.307 に答える
23

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

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

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

[[]]これは移植性が低いことに注意してください[]。ただし、ほとんどの人は最新バージョンのBashを使用しているため(結局のところ、ほとんどの人はコマンドライン:-pを使用していません)、問題よりもメリットが大きくなります。

于 2010-02-17T17:46:07.773 に答える
23

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

cdmv、などでも同じことが機能しrmます...存在しないファイルでそれらを試すと、エラーで終了し、存在しないというメッセージが出力され、thenブロックがスキップされます。存在するファイルでそれらを試すと、コマンドが実行され、ステータスで終了し、ブロックを実行0できるようになります。then

于 2017-12-07T16:24:23.760 に答える
20
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

注意: 変数をクォートすることは良い習慣です。

説明:

  • -d: ディレクトリかどうかを確認します
  • -L: シンボリック リンクかどうかを確認します
于 2015-04-19T00:54:07.030 に答える
17

複数のディレクトリを確認するには、次のコードを使用します。

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi
于 2015-12-29T09:45:14.513 に答える
16

ディレクトリが存在するかどうかを確認し、存在しない場合は作成します。

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
于 2016-03-23T07:25:55.557 に答える
12

この回答はシェルスクリプトとしてまとめられています

$ 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";
于 2016-04-15T18:13:53.633 に答える
9
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
于 2010-03-18T10:52:57.553 に答える
9

ジョナサンのコメントによると:

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

mkdir -p /some/directory/you/want/to/exist || exit 1
于 2015-09-12T21:21:06.503 に答える
7

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

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

[[ $(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
于 2011-09-15T19:47:49.540 に答える
6
file="foo" 
if [[ -e "$file" ]]; then echo "File Exists"; fi;
于 2013-02-22T02:39:07.313 に答える
6

以下findを使用できます。

find . -type d -name dirname -prune -print
于 2014-08-13T13:41:35.353 に答える
4

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

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」を返し、「$?」で取得できる戻りコードを非に設定します。 -null (通常は「1」)。「ls」を呼び出した直後に、必ずリターン コードを確認してください。

于 2014-01-07T17:59:56.567 に答える