如何在bash的for循环中传递具有特定扩展名的文件列表

如何在bash的for循环中传递具有特定扩展名的文件列表,bash,argument-passing,Bash,Argument Passing,首先,大家好,这是我在这里的第一篇帖子。 我发誓我已经检查过网站上类似的问题,以避免“关于同一论点的双重帖子”的问题,但没有一个完全回答了我的问题。 问题是,在下面的代码中,当我调用脚本并将扩展名作为第一个参数传递给它时,总是会收到“没有具有此扩展名的文件”消息 #!/bin/bash if [ "$1" ]; then file=*."$1"; if [ -f "$file" ]; then for

首先,大家好,这是我在这里的第一篇帖子。 我发誓我已经检查过网站上类似的问题,以避免“关于同一论点的双重帖子”的问题,但没有一个完全回答了我的问题。 问题是,在下面的代码中,当我调用脚本并将扩展名作为第一个参数传递给它时,总是会收到
“没有具有此扩展名的文件”
消息

#!/bin/bash
if [ "$1" ];
    then
        file=*."$1";
        if [ -f "$file" ];
            then
                for i in "$file";
                [...do something with the each file using "$i" like echo "$i"]
            else
                echo "There are no files with this extension";
        fi;
     else
         echo "You have to pass an extension"
     fi;

我尝试使用双括号,在嵌套的if中使用引号,在if中直接使用“$1”,但这些解决方案都不起作用。

一个问题是,当您第一次为
文件指定值时,您没有引用变量。在本声明中:

    file=*."$1";
*
将由shell解释,因此,例如,如果您在命令行上传入了
.py
,文件可能会以值
file1.py file2.py
结束,这将在稍后取消文件存在性测试

正如@sideshowbarker指出的,另一个问题是不能将通配符和
[-f…]
一起使用

另一个变量引用问题是,引用禁止通配符扩展,因此即使没有文件存在性测试,如果
$file
是,例如
*.txt
,那么:

for x in "$file"; do ...
将循环使用文本值
*.txt
的单个参数,而:

for x in $file; do ...
将循环所有以
.txt
扩展名结尾的文件(除非没有扩展名,在这种情况下,它将循环一次,并将
$x
设置为文本值
*.txt

通常,编写脚本时需要一个参数列表,并允许用户像调用
myscript*.txt
一样调用它。也就是说,将通配符处理留给交互式shell,只让脚本处理一个参数列表。然后它变得简单:

for i in "$@"; do
  echo do something with this file named "$x"
done
如果您真的想处理脚本中的通配符扩展,以下类似操作可能会奏效:

#!/bin/bash
if [ "$1" ];
    then
        ext="$1"
        for file in *.$ext; do
            [ -f "$file" ] || continue
            echo $file
        done
     else
         echo "You have to pass an extension"
     fi;

由于我前面提到的情况,这里有必要使用语句
[-f“$file”]|
:如果没有文件,循环仍将执行一次,并进行
*。$ext

这只是另一个问题,在这种情况下,我可以在哪里放置
回音“没有具有此扩展名的文件
?我试着将它放在
完成后
但似乎是
[-f“$file”]|继续
如果没有找到匹配的文件,就让脚本停止。在我的示例中,脚本的编写方式很难提供该错误。您可以在
for
循环中维护匹配文件的计数,然后检查该计数是否为
0
。我更新了答案,添加了一个示例,说明如何添加
echo“没有具有此扩展名的文件”
位。