枚舉文件 *.pdf 排除 *_book.pdf

枚舉文件 *.pdf 排除 *_book.pdf

如何列舉目錄中的所有文件文件,並按模式排除。

例如:所有 *.pdf 排除 *_book.pdf。我嘗試這樣:

for $PDF in $(ls *.pdf | grep -v *_book.pdf);
do
   echo "File $PDF"
done

這是個好辦法嗎?還有其他方法嗎?用過的如果聲明或其他。

答案1

不要ls在腳本中使用。

另外,在循環中宣告的變數for不應帶有美元符號。美元符號插值變數的值;所以$PDF讀作“名稱為”的變數的當前值PDF

for PDF in *.pdf
do
    case $PDF in
     *_book.pdf) continue;;
    esac
    echo "File $PDF"
done

這種文法讓一些初學者感到害怕,但對於這樣的事情case我更喜歡它。if但如果您願意,您可以使用

    if [[ $PDF =~ _book\.pdf$ ]]; then
        continue
    fi

或簡寫

    [[ $PDF =~ _book\.pdf$ ]] && continue

case還有一個額外的好處是它可以移植到 POSIXsh甚至是古老的原始 Bourne sh

請注意, in 中的模式case是一個 glob,而 while[[ $variable =~ regex ]]使用正規表示式(因此不應有*before _book)。

答案2

使用shopt -s extglob(這可能是系統上的預設設置,否則進行設定),您可以使用擴展匹配,這包括否定匹配模式:

# Directry contents
>ls -1
1_book_not.pdf
1_book.pdf
1.pdf
1.txt

# With negative match
>ls -1 !(*_book).pdf
1_book_not.pdf
1.pdf

答案3

您的for表達式中有一個輕微的語法錯誤。請嘗試以下方法:

for PDF in $(ls *.pdf | grep -v *_book.pdf);
do
   echo "File $PDF"
done

這看起來效果不錯。

答案4

另一個選擇是使用find

find . -maxdepth 1 -name '*.pdf' ! -name '*_book.pdf'

例如,考慮包含以下四個檔案的目錄:

$ ls
a_book.pdf  book.txt  nook.pdf  not_book1.pdf

現在,運行我們的命令:

$ find . -maxdepth 1 -name '*.pdf' ! -name '*_book.pdf'
./not_book1.pdf
./nook.pdf

怎麼運作的

  • find .告訴 find 在目前目錄中開始搜尋。

  • -maxdepth 1告訴 find 跳過子目錄。

  • -name '*.pdf'告訴 find 找出名稱以 if 結尾的檔案.pdf

  • ! -name '*_book.pdf'告訴 find 從輸出排除任何名稱以_book.pdf.

相關內容