shell判斷檔案是否存在 - 檢查shell腳本中是否存在目錄




ubuntu shell script (20)

在shell腳本中,可以使用什麼命令來檢查目錄是否存在?


使用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
    
  • 根據當前目錄中的模式檢查是否存在一個或多個文件夾:

    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
    

  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':文件存在


ls命令與-l (長列表)選項一起返回有關文件和目錄的屬性信息。
特別是ls -l輸出的第一個字符通常是d或a - (破折號)。 如果是d ,列出的是確定的目錄。

只有一行中的以下命令將告訴您給定的ISDIR變量是否包含目錄的路徑:

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

實際用法:

    [[email protected] ~]$ ISDIR="$HOME/Music" 
    [[email protected] ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [[email protected] ~]$ [[ $(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.

    [[email protected] ~]$ touch "empty file.txt"
    [[email protected] ~]$ ISDIR="$HOME/empty file.txt" 
    [[email protected] ~]$ [[ $(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

下面可以找到,

find . -type d -name dirname -prune -print

你有沒有考慮過做你想做的任何事情而不是在你跳躍之前尋找?

IE,如果要在輸入之前檢查目錄是否存在,請嘗試執行以下操作:

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等...如果你在不存在的文件上嘗試它們,它們將退出並出現錯誤並打印一條消息,說它不存在,然後你的塊將是跳過。 如果您對存在的文件進行嘗試,該命令將執行並以狀態0退出,允許您執行then塊。


使用-e檢查將檢查文件,這包括目錄。

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

如果要檢查目錄是否存在,無論它是真實目錄還是符號鏈接,請使用以下命令:

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

說明:如果目錄或符號鏈接不存在,“ls”命令會給出錯誤“ls:/ x:沒有這樣的文件或目錄”,並且還可以通過“$?”將返回代碼設置為非-null(通常為“1”)。 確保在調用“ls”後直接檢查返回碼。


實際上,您應該使用幾種工具來獲得防彈方法:

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),所以效益大於麻煩。


或者對於完全沒用的東西:

[ -d . ] || echo "No"

根據評論:

如果你想創建目錄但它還不存在,那麼最簡單的方法是使用mkdir -p創建目錄 - 以及路徑上任何缺少的目錄 - 如果目錄已經存在則不會失敗,所以你可以用以下方法一次完成所有操作:

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

注意-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條件表達式[ builtin命令以及[[複合 命令]的更多信息)。


縮短形式:

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

要檢查多個目錄,請使用以下代碼:

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi

要檢查目錄是否存在,您可以使用簡單的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 

這個答案包含在一個shell腳本中

例子

$ 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";

這是一個非常實用的習語:

(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會給stderr標準的一行消息。 它還將提供比我能提供的更多信息。 通過在子shell ( ... )執行cd ,該命令不會影響調用者的當前目錄。 如果目錄存在,則此子shell和函數只是一個無操作。

接下來是我們傳遞給cd的參數: ${1:?pathname expected} 。 這是參數替換的更精細形式,下面將更詳細地解釋。

Tl; dr:如果傳入此函數的字符串為空,我們再次退出子shell ( ... )並從具有給定錯誤消息的函數返回。

引自ksh93手冊頁:

${parameter:?word}

如果parameter設置且非null,則替換其值; 否則,打印word並退出shell(如果不是交互式)。 如果省略word則打印標準消息。

如果從上面的表達式中省略了冒號:那麼shell只檢查參數是否設置。

這裡的措辭是shell文檔所特有的,因為word可以引用任何合理的字符串,包括空格。

在這種特殊情況下,我知道標準錯誤消息1: parameter not set是不夠的,所以我放大了我們期望的值類型 - 目錄的pathname

philosphical note:shell不是面向對象的語言,因此消息顯示pathname ,而不是directory 。 在這個層面上,我寧願保持簡單 - 函數的參數只是字符串。


[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"

[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

注意:引用變量是一種很好的做法。


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

這不完全正確......如果要轉到該目錄,還需要擁有該目錄的執行權限。 也許你還需要擁有寫權。

Therfore:

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

if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi




posix