簡體   English   中英

在bash中循環瀏覽指定擴展名的文件

[英]Looping through files of specified extensions in bash

我試圖用bash腳本遍歷指定擴展名列表的文件。 我嘗試了使用for循環具有各種擴展名的文件匹配中給出的解決方案,但是它無法按預期工作。 給出的解決方案是:

for file in "${arg}"/*.{txt,h,py}; do

這是我的版本:

for f in "${arg}"/*.{epub,mobi,chm,rtf,lit,djvu}
    do
        echo "$f"
    done

當我在其中包含epub文件的目錄中運行此文件時,我得到:

/*.epub
/*.mobi
/*.chm
/*.rtf
/*.lit
/*.djvu

所以我嘗試更改for語句:

for f in "${arg}"*.{epub,mobi,chm,rtf,lit,djvu}

然后我得到:

089281098X.epub
*.mobi
*.chm
*.rtf
*.lit
*.djvu

我也得到相同的結果:

for f in *.{epub,mobi,chm,rtf,lit,djvu}

因此,似乎不需要"${arg}"參數。

盡管這兩個語句都可以找到指定擴展名的文件並將其傳遞給程序,但是我從未解析的*.讀取了錯誤*. 文件名。

我正在OS X Mountain Lion上運行它。 我知道的是,默認的bash shell已經過時了,所以我升級從3.2.484.2.45使用homebrew ,看看這是問題。 那沒有幫助,所以我想知道為什么我得到了這些意外的結果。 給定的解決方案是錯誤的,還是OS X bash shell與*NIX版本有所不同? 也許有另一種方法可以完成在OS X bash shell中可能會更好地完成相同任務的事情?

這可能是BASH 4.2ism。 它在我的BASH(仍為3.2)中不起作用。 但是,如果您shopt -s extglob ,則可以使用*(...)代替:

shopt -s extglob
for file in *.*(epub|mobi|chm|rtf|lit|djvu)
do
    ...
done

@David W.:f中的shopt -s extglob (epub | mobi | chm | rtf | lit | djvu)結果為:089281098X.epub @kojiro:arg =。 在“ $ {arg}” /中的f的shopt -s nullglob 。{epub,mobi,chm,rtf,lit,djvu}結果為:./089281098X.epub在“ $ {arg}”中的f的shopt -s nullglob 。 {epub,mobi,chm,rtf,lit,djvu}結果為:089281098X.epub因此,所有這些變體都有效,但我不明白為什么。 你們兩個都可以解釋每種變化的情況以及$ {arg}在做什么嗎? 我真的很想了解這一點,所以我可以增加我的知識。 謝謝您的幫助。

在我的:

for f in *.*(epub|mobi|chm|rtf|lit|djvu)

我沒有包含擴展為$arg的值的$arg ${arg} *(...)與括號中的模式匹配,該括號是一系列擴展中的任何一個。 因此,它匹配*.epub

小次郎的:

arg=. 
shopt -s nullglob 
for f in "${arg}"/*.{epub,mobi,chm,rtf,lit,djvu}

在他的匹配中包括$arg和斜杠。 因此,koriro以./開頭,因為這就是他們的要求。

就像之間的區別:

echo *

echo ./*

順便說一句,您也可以使用其他表達式來執行此操作:

echo *.*(epub|mobi|chm|rtf|lit|djvu)

Shell正在為您完成所有擴展。 它實際上與for語句本身無關。

全局名稱必須擴展為現有的已找到名稱,否則將保留原樣的星號。 如果目錄為空,則*.foo將擴展為*.foo (除非您使用nullglob Bash擴展名。)

代碼的問題是,您以arg $arg開頭,該參數顯然為空或未定義。 因此,由於根目錄中沒有以“ .epub”結尾的文件,因此${arg}/*.epub 。epub會擴展為/*.epub 它永遠不會在當前目錄中查找。 為此,您需要設置arg=. 第一。

在第二個示例中, ${arg}*.epub確實會擴展,因為$arg為空,但是其他文件不存在,因此它們不會繼續擴展為全局文件。 正如我在之前暗示,一個簡單的解決方法是激活nullglobshopt -s nullglob 這是bash特定的,但是如果沒有匹配的文件,它將導致*.foo擴展為空字符串。 對於嚴格的POSIX解決方案,您必須使用[ -f "$f" ]過濾掉未擴展的glob。 (然后再次,如果您想要POSIX,則也不能使用括號擴展。)

總而言之,最好的解決方案是使用(最直觀,最優雅):

shopt -s extglob
for f in *.*(epub|mobi|chm|rtf|lit|djvu)

或者,為了與所引用線程中給出的原始解決方案保持一致(如上所述,這是錯誤的):

shopt -s nullglob
for f in "${arg}"*.{epub,mobi,chm,rtf,lit,djvu}

應該這樣做:

for file in $(find ./ -name '*.epub' -o -name '*.mobi' -o -name '*.chm' -o -name '*.rtf' -o -name '*.lit' -o -name '*.djvu'); do
  echo $file
done

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM