Linux 递归查找具有特定扩展名的文件
我试图用我的bash(最新的ubuntults版本)在一个目录及其子目录中找到所有具有特定扩展名的文件 这是在脚本文件中写入的内容: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
#!/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手册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等的文件名,我特别解释这就是它被破坏的原因。在讨论中提供参考始终是一种很好的方式,它不取决于谁是第一个。他应该,你应该。错误来自于一个缺失的{'Thegrep
在这里并不是必需的。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"