繁体   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