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

时间:2011-05-08 12:21:41

标签: linux bash recursion

我正在尝试使用我的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'

这里发生了什么,哪里出错? 但是这个大括号

10 个答案:

答案 0 :(得分:654)

find $directory -type f -name "*.in"

比整个事情要短一些(更安全 - 处理文件名和目录名中的空格)。

对于名称中没有.的条目,$extension为空,您的脚本可能会失败。

答案 1 :(得分:148)

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

示例 查找当前目录及其子目录中的所有csv文件

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

答案 2 :(得分:58)

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

find $directory -type f -name \*.in

(这是一次击键次数。)

答案 3 :(得分:12)

不使用find

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

答案 4 :(得分:10)

  1. {
  2. 后遗失了browsefolders ()
  3. 所有$in应为$suffix
  4. cut行只会让您front.middle.extension的中间部分。您应该阅读${varname%%pattern}和朋友们的shell手册。
  5. 我假设您将此作为shell脚本编写的练习,否则已提出的find解决方案是可行的方法。

    要检查正确的shell语法,而不运行脚本,请使用sh -n scriptname

答案 5 :(得分:6)

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

find . -name 'pom.xml' -print

答案 6 :(得分:3)

尽管在这里使用find命令很有用,但是shell本身提供了实现此要求的选项,而无需任何第三方工具。 bash外壳程序提供了扩展的glob支持选项,通过该选项,您可以在与所需扩展名匹配的递归路径下获取文件名。

扩展选项为extglob,需要使用shopt选项进行设置,如下所示。这些选项在-s支持下启用,在-u标志下禁用。另外,您可以使用更多选项,例如nullglob,其中不匹配的glob会被完全清除,而用一组零个单词代替。并且globstar允许遍历所有目录

shopt -s extglob nullglob globstar

现在,您所需要做的就是形成glob表达式,以包含某个扩展名的文件,您可以按以下方式进行操作。我们使用数组来填充全局结果,因为当正确地引用和扩展它们时,带有特殊字符的文件名将保持不变,并且不会由于shell的单词拆分而损坏。

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

fileList=(**/*.csv)

选项**是通过子文件夹递归的,而*.csv是全局扩展,以包括上述扩展的任何文件。现在要打印实际文件,只需执行

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

在shell脚本中使用数组并进行适当的带引号的扩展是正确的方法,但是对于交互使用,您可以简单地将ls与glob表达式一起使用

ls -1 -- **/*.csv

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

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

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

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

结构!()是一个否定运算,不包括内部列出的任何文件扩展名,而|是一个交替运算符,正如在Extended Regular Expressions库中用来对小球。

请注意,这些扩展的glob支持在POSIX bourne shell中不可用,其纯粹针对bash的最新版本。因此,如果您正在考虑跨POSIX和bash shell运行的脚本的可移植性,则此选项不合适。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

for file in "${LOCATION_VAR}"/*.zip
do
  echo "$file"
done 

答案 9 :(得分:0)

os.system('apt install program etc...')