查找具有用户指定扩展名的文件

查找具有用户指定扩展名的文件

我正在编写一个脚本,该脚本将多个文件扩展名作为逗号分隔的字符串,并使用它来列出特定目录结构中的文件,但提供的扩展名数量可能会有所不同。

我正在使用的查找命令是

     find ./ -type f \( -iname \*.ksh -o -iname \*.cfg \)

此处用户正在搜索 ksh 和 cfg 文件。但用户可能只能找到 ksh 、 cfg 或更多扩展。有没有办法使搜索模式对任意数量的扩展通用?

答案1

假设您将文件名后缀作为单独的命令行参数获取(有关如何处理逗号分隔字符串的信息,请参阅答案末尾):

#!/bin/sh

for suffix do
    set -- "$@" -o -iname "*.$suffix"
    shift
done

shift

find . -type f \( "$@" \)

该脚本将被称为

./script.sh ksh cfg

它会将$suffix位置参数中的每个后缀替换为-o -iname "*.$suffix".

shift调用之前的唯一的find删除了首字母-oin "$@"

ksh93在or中使用数组bash

#!/bin/ksh

name_opts=()

for suffix do
    name_opts+=( -o -iname "*.$suffix" )
done

find . -type f \( "${name_opts[@]:1}" \)

in:1丢弃数组"${name_opts[@]:1}"的第一个元素name_opts(初始的-o)。


如果您确实想要以逗号分隔的字符串形式获取后缀(这意味着您无法使用脚本来查找文件名后缀中带有逗号的文件,例如 RCS 或 CVS 存储中的文件),您可以转换该字符串, $list, 到数组中bashksh93

set -f
suffixes=( ${list//,/ } )
set +f

sh

set -f
set -- $( printf '%s\n' "$list" | tr ',' ' ' )
set +f

或者

set -f; ifs=$IFS; IFS=','
set -- $list
set +f; IFS=$ifs; unset ifs

(这些将位置参数设置为后缀列表)。

set -f文件名生成(通配符),因为我们依赖 shell 在替换逗号的空格上分割字符串,但是不是使用生成的单词进行通配。如果没有,set -f我们将无法正确处理对[ch]或等后缀的请求*

bashor中的循环ksh将从

for suffix do ...

for suffix in "${suffixes[@]}"; do ...

而循环sh将保持原样。

答案2

您可以使用扩展正则表达式来-iregex代替多个段:-iname

GNU find

find . -type f -regextype egrep -iregex '.*\.(ksh|cfg)$'

免费BSD find

find -E  . -type f -iregex '.*\.(ksh|cfg)$' 

如果变量中已有逗号分隔的扩展名(例如$csep),请将它们转换为正则表达式替换 ( |)。第一的。例如

csep='ksh,sh,cfg,csv'
re="$(echo "$csep" | tr , '|')"
find . -type f -regextype egrep -iregex ".*\.($re)$"
#BSD: find -E . -type f -iregex ".*\.($re)$"

如果您需要支持其中包含逗号的扩展,您可以使用,sed来代替tr, 以允许反斜杠转义逗号 ( \,)。例如

$ csep='ksh,sh,cfg,csv,c\,v'
$ re="$(echo "$csep" | sed -Ee 's/([^\]),/\1|/g')"
$ printf '%b\n' "$re"
ksh|sh|cfg|csv|c\,v

相关内容