[英]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.