Linux 递归查找具有特定扩展名的文件

Linux 递归查找具有特定扩展名的文件,linux,bash,recursion,Linux,Bash,Recursion,我试图用我的bash(最新的ubuntults版本)在一个目录及其子目录中找到所有具有特定扩展名的文件 这是在脚本文件中写入的内容: #!/bin/bash directory="/home/flip/Desktop" suffix="in" browsefolders () for i in "$1"/*; do echo "dir :$directory" echo "filename: $i" # echo ${i#*.} extensio

我试图用我的bash(最新的ubuntults版本)在一个目录及其子目录中找到所有具有特定扩展名的文件

这是在脚本文件中写入的内容:

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*; 
  do
    echo "dir :$directory"
    echo "filename: $i"
    #   echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then        

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    elif [ -d "$i" ]; then  
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"
不幸的是,当我在终端启动这个脚本时,它说:

[: 29: in: unexpected operator
(使用
$extension
代替
'in'

这里发生了什么,哪里出错了? 但是这个卷曲的支架

find $directory -type f -name "*.in"
比整个过程要短一点(而且更安全——处理文件名和目录名中的空白)

对于名称中没有
的条目,脚本可能会失败,从而使
$extension
为空

  • 浏览文件夹()
  • 中的所有
    $应为
    $后缀
  • 带有
    cut
    的行只显示
    front.middle.extension
    的中间部分。您应该阅读
    ${varname%%pattern}
    和朋友们的shell手册
  • 我假设您这样做是作为shell脚本编写的练习,否则,已经提出的
    find
    解决方案就是一条出路


    要检查shell语法是否正确,在不运行脚本的情况下,请使用
    sh-nScriptName

    我使用的语法与@Matt建议的有点不同:

    find $directory -type f -name \*.in
    
    (只需少敲一次键)

    示例:要查找当前目录及其子目录中的所有
    csv
    文件,请使用:

    find . -type f -name '*.csv'
    

    要查找当前目录中的所有
    pom.xml
    文件并打印它们,您可以使用:

    find . -name 'pom.xml' -print
    

    不使用
    查找

    du -a $directory | awk '{print $2}' | grep '\.in$'
    

    虽然在这里使用
    find
    命令很有用,但是shell本身提供了一些选项,可以在不使用任何第三方工具的情况下实现这一要求。
    bash
    shell提供了一个扩展的glob支持选项,使用该选项,您可以在递归路径下获得与所需扩展名匹配的文件名

    扩展选项是
    extglob
    ,需要使用下面的
    shopt
    选项进行设置。这些选项通过
    -s
    支持启用,并通过
    -u
    标志禁用。此外,您还可以使用更多选项,即
    nullglob
    将不匹配的glob全部清除使用一组零字进行编辑。和
    globstar
    ,允许在所有目录中递归

    shopt -s extglob nullglob globstar
    
    现在,您所需要做的就是形成glob表达式,以包含具有特定扩展名的文件,您可以如下所示。我们使用数组填充glob结果,因为当正确引用并展开时,具有特殊字符的文件名将保持不变,并且不会因shell拆分单词而被破坏

    例如,列出递归路径中的所有
    *.csv
    文件

    fileList=(**/*.csv)
    
    选项
    **
    是在子文件夹中递归,而
    *.csv
    是全局扩展,以包含所述扩展名的任何文件。现在要打印实际文件,只需执行以下操作

    printf '%s\n' "${fileList[@]}"
    
    当在shell脚本中使用时,使用数组并进行适当的引号扩展是正确的方法,但是对于交互式使用,您可以简单地使用glob表达式作为

    ls -1 -- **/*.csv
    
    <>这可以很好地扩展到匹配多个文件,即文件以多个扩展结束(即类似于在代码中添加多个标志>查找< /COD>命令)。例如,需要得到所有递归图像文件,即扩展名<代码> *.GIF < /代码>,<代码> *.png< /> >和<代码> *.jpg < /代码>,所有您需要的是

    ls -1 -- **/+(*.jpg|*.gif|*.png)
    
    这也可以扩展为具有否定结果。使用相同的语法,可以使用glob的结果来排除某些类型的文件。假设要排除具有上述扩展名的文件名,可以这样做

    excludeResults=()
    excludeResults=(**/!(*.jpg|*.gif|*.png))
    printf '%s\n' "${excludeResults[@]}"
    
    构造
    !()
    是一个否定操作,不包括其中列出的任何文件扩展名,
    |
    是一个交替运算符,就像在扩展正则表达式库中用于执行全局函数的OR匹配一样


    请注意,这些扩展的glob支持在POSIX bourne shell中不可用,并且仅限于最新版本的
    bash
    。因此,如果您正在考虑跨POSIX和
    bash
    shell运行的脚本的可移植性,则此选项将不正确。

    是的,
    find
    默认情况下是递归的。您可以限制如果您愿意,请输入深度(请参阅手册页)。我想将所有找到的文件作为参数传递给jar文件。如何执行此操作?@flip:这是另一个问题。发布一个新问题,详细说明您想做什么以及迄今为止尝试了什么。一个小更正:使用“*.in”或\*.in代替“*.in”因为双引号不能阻止shell扩展。也就是说,如果当前目录中有扩展名为.in的文件,脚本将无法正常工作。@Shnatsel:双引号确实可以阻止shell扩展。请尝试一下。如果当前目录中有扩展名为.in的文件,Matt的脚本也无法工作,而您的脚本仍然可以工作。请参阅@shnatsel这个评论(以及你的评论)是完全错误的。@gniourf_gniourf你应该为你的陈述提供一些参考,否则你可以简单地说:“不,你错了”但事实上你是对的:@user1885518:我认为应该是那个声称脚本不起作用的人,应该提供一些脚本失败的例子。这就是我在有坏脚本的地方留下评论时所做的:通常是关于引号和包含空格、换行符、glob等的文件名,我特别解释这就是它被破坏的原因。在讨论中提供参考始终是一种很好的方式,它不取决于谁是第一个。他应该,你应该。错误来自于一个缺失的{'The
    grep
    在这里并不是必需的。
    awk
    有正则表达式,可以将其输出限制为与模式匹配的值。如果您要
    find "$PWD" -type f -name "*.in"
    
    ls -1 -- **/+(*.jpg|*.gif|*.png)
    
    excludeResults=()
    excludeResults=(**/!(*.jpg|*.gif|*.png))
    printf '%s\n' "${excludeResults[@]}"
    
    find "$PWD" -type f -name "*.in"