如何檢查 Linux Bash 腳本中是否存在文件

已發表: 2022-08-18
顯示 bash 提示符的 Linux 筆記本電腦
fatmawati achmad zaenuri/Shutterstock.com

如果 Linux Bash 腳本依賴於存在的某些文件或目錄,則不能假設它們確實存在。 它需要檢查它們是否確實存在。 這是如何做到這一點的。

不要假設任何事情

當您編寫腳本時,您無法對計算機上存在和不存在的內容做出假設。 如果腳本要在許多不同的計算機上分發和運行,那就更是如此。 遲早,該腳本將在不符合您的假設的計算機上運行,並且該腳本將失敗或無法預測地運行。

我們在計算機上重視或創建的所有內容都存儲在某種格式的文件中,所有這些文件都位於一個目錄中。 腳本可以讀取、寫入、重命名、刪除和移動文件和目錄——所有你可以在命令行上做的事情。

作為人類,您擁有的優勢是您可以看到目錄的內容,並且知道文件是否存在,或者預期的目錄是否存在。 如果腳本在操作文件時出錯,可能會產生嚴重的破壞性後果。

Bash 提供了一套全面的測試,您可以使用它們來檢測文件和目錄,並測試它們的許多屬性。 將這些合併到腳本中很容易,但在健壯性和精細控制方面的好處是相當可觀的。

相關:如何在 Linux 中使用雙括號條件測試

測試範圍

通過將 if 語句與來自大量文件和目錄測試的適當測試相結合,我們可以輕鬆確定文件是否存在、是否可執行或可寫等等。

  • -b :如果文件是塊特殊文件,則返回 true。
  • -c :如果文件是特殊字符,則返回 true。
  • -d :如果“文件”是目錄,則返回 true。
  • -e :如果文件存在,則返回 true。
  • -f :如果文件存在並且是常規文件,則返回 true。
  • -g :如果文件具有setgid權限集 ( chmod g+ ),則返回 true。
  • -h :如果文件是符號鏈接,則返回 true。
  • -L :如果文件是符號鏈接,則返回 true。
  • -k :如果設置了粘性位( chmod +t ),則返回 true。
  • -p :如果文件是命名管道,則返回 true。
  • -r :如果文件可讀,則返回 true。
  • -s :如果文件存在且不為空,則返回 true。
  • -S :如果文件是套接字,則返回 true。
  • -t :如果文件描述符在終端中打開,則返回 true。
  • -u :如果文件具有setuid權限集 ( chmod u+ ),則返回 true。
  • -w :如果文件是可寫的,則返回 true。
  • -x :如果文件是可執行的,則返回 true。
  • -O :如果歸您所有,則返回 true。
  • -G :如果歸您的組所有,則返回 true。
  • -N :如果文件自上次讀取後已被修改,則返回 true。
  • : 邏輯非運算符。
  • && :邏輯與運算符。
  • || :邏輯或運算符。

該列表以-b開頭,因為-a測試已被棄用並被-e測試取代。

相關:如何在 Linux 上使用 SUID、SGID 和 Sticky Bits

在腳本中使用測試

通用文件 test if語句是一個簡單的腳本構造。 雙括號“ [[ ]] ”內的比較使用-f測試來確定是否存在具有該名稱的常規文件。

將此腳本的文本複製到編輯器中並將其保存到名為“script1.sh”的文件中,並使用chmod使其可執行。

 #!/bin/bash

如果 [[ -f $1 ]] 

然後 

  echo "文件 $1 存在。" 

別的 

  echo "找不到文件 $1。" 

菲

您必須將文件名傳遞給命令行上的腳本。

 chmod +x script1.sh 

使用 chmod 使腳本可執行

如果您想嘗試本文中的其他示例,則需要對每個腳本執行此操作。

讓我們在一個簡單的文本文件上嘗試腳本。

 ./script1.sh 測試文件.txt 

在常規文件上運行 script1.sh

該文件存在並且腳本正確地報告了這一事實。 如果我們刪除文件並重試,測試應該會失敗並且腳本應該向我們報告。

 ./script1.sh 測試文件.txt 

對不存在的文件運行 script1.sh

在現實生活中,您的腳本需要採取任何適當的行動。 也許它會標記錯誤並停止。 也許它會創建文件並繼續。 它可能會從備份目錄中復制一些內容以替換丟失的文件。 這完全取決於腳本的目的。 但至少現在腳本能夠根據知道文件是否存在來做出決定。

-f標誌測試文件是否存在,並且是“常規”文件。 換句話說,它不是看起來是文件但實際上不是的東西,例如設備文件。

我們將使用 ls 來驗證“/dev/random”文件是否存在,然後查看腳本是如何構成的。

 ls -lh /dev/隨機
./script /dev/random 

對設備文件運行 script1.sh

因為我們的腳本正在測試常規文件,而“/dev/random”是設備文件,所以測試失敗。 很多時候,要查明文件是否存在,您需要仔細選擇您使用的測試,或者您需要使用多個測試。

這是“script2.sh”,用於測試常規文件和字符設備文件。

 #!/bin/bash

如果 [[ -f $1 ]]
然後
  echo "文件 $1 存在。"
別的
  echo "文件 $1 丟失或不是常規文件。"
菲

如果 [[ -c $1 ]]
然後
  echo "文件 $1 是字符設備文件。"
別的
  echo "文件 $1 丟失或不是特殊文件。" 
菲

如果我們在“/dev/random”設備文件上運行這個腳本,第一個測試會失敗,而第二個測試會成功。 它將文件識別為設備文件。

 ./script2.sh /dev/random 

對字符設備文件運行 script2.sh

實際上,它將其識別為字符設備文件。 一些設備文件是塊設備文件。 就目前而言,我們的腳本無法處理這些問題。

 ./script2.sh /dev/sda 

對塊設備文件運行 scrip2.sh

我們可以使用邏輯OR運算符並在第二個 if 語句中包含另一個測試。 這一次,無論文件是字符設備文件還是塊設備文件,測試都會返回true。 這是“script3.sh”。

 #!/bin/bash

如果 [[ -f $1 ]]
然後
  echo "文件 $1 存在。"
別的
  echo "文件 $1 丟失或不是常規文件。"
菲

如果 [[ -c $1 || -b $1 ]]
然後
  echo "文件 $1 是字符或塊設備文件。"
別的
  echo "文件 $1 丟失或不是特殊文件。" 
菲

此腳本識別字符設備和塊設備文件。

 ./script3.sh /dev/random
 ./script3.sh /dev/sda 

script3.sh 正確處理字符和塊設備文件

如果區分不同類型的設備文件對您很重要,您可以使用嵌套if語句。 這是“script4.sh”。

 #!/bin/bash

如果 [[ -f $1 ]]
然後
  echo "文件 $1 存在。"
別的
  echo "文件 $1 丟失或不是常規文件。"
菲

如果 [[ -c $1 ]]
然後
  echo "文件 $1 是字符設備文件。"
別的
  如果 [[ -b $1 ]]
  然後
    echo "文件 $1 是一個塊設備文件。" 
  別的
    echo "文件 $1 丟失或不是設備文件。"
  菲
菲

此腳本識別字符設備和塊設備文件並對其進行分類。

 ./script4.sh /dev/random
 ./script4.sh /dev/sda 

script8.sh 正確識別字符和塊設備文件

使用邏輯 AND 運算符,我們可以一次測試多個特徵。 這是“script5.sh”。 它檢查文件是否存在並且腳本對其具有讀寫權限。

 #!/bin/bash

如果 [[ -f $1 && -r $1 && -w $1 ]]
然後
  echo "文件 $1 存在,我們有讀/寫權限。"
別的
  echo "文件 $1 丟失,不是普通文件,或者我們無法讀取/寫入它。"
菲

我們將在屬於我們的文件和屬於root的文件上運行腳本。

 ./script5.sh .bashrc
 ./script5.sh /etc/fstab 

script5.sh 檢查文件是否存在以及是否設置了讀寫權限

要測試目錄是否存在,請使用-d測試。 這是“script6.sh”。 它是備份腳本的一部分。 它做的第一件事是檢查命令行傳遞的目錄是否存在。 它使用邏輯NOT運算符!if語句測試中。

 #!/bin/bash

如果 [[ ! -d $1 ]]
然後
  echo "創建備份目錄:" $1
  mkdir $1

  如果 [[ ! 美元? -eq 0 ]]
  然後
    echo "無法創建備份目錄:" $1
    出口
  菲
別的
  echo "備份目錄存在。"
菲

# 繼續備份文件
echo "備份到:"$1

如果該目錄不存在,它會創建它。 如果目錄創建文件,則腳本退出。 如果目錄創建成功,或者目錄已經存在,則腳本將繼續執行其備份操作。

我們將運行腳本,然後使用ls-d (目錄)選項檢查備份目錄是否存在。

 ./script6.sh 文件/project-backup
 ls -d 文檔/項目備份

script6.sh 檢測目錄是否存在

備份目錄已創建。 如果我們再次運行腳本,它應該報告該目錄已經存在。

 ./script6.sh 

script6.sh 重用現有目錄

該腳本找到目錄並繼續執行備份。

測試,不要假設

遲早,假設會導致壞事發生。 先測試,然後做出相應的反應。

知識就是力量。 使用測試為您的腳本提供所需的知識。

相關:如何讓 Linux 腳本檢測它們在虛擬機中運行