[英]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.48
到4.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
為空,但是其他文件不存在,因此它們不會繼續擴展為全局文件。 正如我在之前暗示,一個簡單的解決方法是激活nullglob
與shopt -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.