我试图在我的bash(最新的Ubuntu LTS发行版)的目录及其子目录中找到具有特定扩展名的所有文件。

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

#!/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"|grep $substring

其他回答

find $directory -type f -name "*.in"|grep $substring
find "$directory" -type f -name "*.in"

比整个代码略短(而且更安全——处理文件名和目录名中的空白)。

您的脚本可能会失败的条目没有。以他们的名字,使$extension为空。

find {directory} -type f -name '*.extension'

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

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

browsefolders()后面缺少一个{ 所有的$in都应该是$后缀 有切口的线只能得到front.mid .extension的中间部分。你应该阅读你的shell手册关于${varname%%pattern}和朋友。

我假设您将此作为shell脚本的练习,否则就应该使用已经提出的find解决方案。

如果不运行脚本,使用sh -n scriptname检查shell语法是否正确。

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

扩展选项是extglob,需要使用下面的shop选项设置。该选项通过-s支持启用,通过he -u标志禁用。此外,你可以使用更多的选项,如nullglob,其中一个不匹配的glob被完全扫走,替换为一组零字。globstar可以递归遍历所有目录

shopt -s extglob nullglob globstar

现在,您所需要做的就是形成glob表达式,以包含某个扩展名的文件,您可以如下所示。我们使用一个数组来填充glob结果,因为当正确地引用并展开时,具有特殊字符的文件名将保持完整,并且不会由于shell的分词而被破坏。

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

fileList=(**/*.csv)

选项**是递归遍历子文件夹,*.csv是glob扩展,以包括上述扩展名的任何文件。现在打印实际文件,就这样做

printf '%s\n' "${fileList[@]}"

在shell脚本中使用数组并使用适当的引号展开是正确的方式,但对于交互式使用,您可以简单地使用ls和glob表达式as

ls -1 -- **/*.csv

这可以很好地扩展到匹配多个文件,即文件以多个扩展名结尾(即类似于在find命令中添加多个标志)。例如,考虑一个需要获得所有递归图像文件的情况,即扩展名*.gif, *.png和*.jpg,所有你需要的是

ls -1 -- **/+(*.jpg|*.gif|*.png)

这很可能被扩展为否定的结果。使用相同的语法,可以使用glob的结果排除特定类型的文件。假设您希望排除具有上述扩展名的文件名,您可以这样做

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

构造!()是一个求反操作,不包括其中列出的任何文件扩展名,|是一个替换操作符,就像在扩展正则表达式库中使用的那样,用于对glob进行OR匹配。

请注意,这些扩展的glob支持在POSIX bourne shell中是不可用的,它纯粹是针对bash的最新版本。因此,如果您正在考虑在POSIX和bash shell之间运行的脚本的可移植性,那么这个选项是不正确的。