Bash脚本,find命令,使用通配符或正则表达式

时间:2019-06-14 13:11:06

标签: linux bash command-line find

我正在编写一个bash脚本,该脚本遍历某些目录中的所有文件,并且:

  1. 选择名称与指定模式匹配的文件
  2. 按数据和时间排序(日期和时间是文件名的一部分)
  3. 获取X个最早的文件
  4. 对它们执行某些操作

用于匹配文件的模式将传递给脚本,如下所示:

someprefix_[cats|dogs]_[oranges|apples|tomatos]_[2|3]*.txt

我尝试按以下方式实现它(假定模式中的字段6和7包含日期和时间):

FILES=`find . -name "$PATTERN” | sort -t_ -k6 | head -n $NUM_OF_FILES`

它不起作用。 尝试了-name-regex的各种选项。 在线上的大多数示例都是针对不太复杂的模式的。 由于可能要处理数十万个文件,因此我正在寻找一种有效的解决方案。 出于可读性原因,我想避免使用sed。

3 个答案:

答案 0 :(得分:2)

您的find正则表达式必须匹配find返回的整个路径。例如,如果您正在somedir/中搜索文件,则您的正则表达式必须匹配,例如

somedir/prefix_cats_apples_2.txt

使图片复杂化的是,您是否可以通过将-regextype选项更改为find来使用多种正则表达式,例如emacs (default), posix-awk, posix-basic, posix-egrep, posix-extended。 (posix-basic没有更改功能)

posix-egrep可能是您的工具之间最可移植的工具,例如grep, sed, find, etc..用于posix-egrep中搜索文件的somedir/正则表达式是:

'somedir/prefix_(cats|dogs)_(apples|oranges|tomatos).*[23].*$'

使用文件名匹配测试(文件尾号为0-3,以排除以0, 1结尾的文件),使用了以下示例文件:

$ls -1 somedir/
prefix_cats_apples_0.txt
prefix_cats_apples_1.txt
prefix_cats_apples_2.txt
prefix_cats_apples_3.txt
prefix_cats_oranges_0.txt
prefix_cats_oranges_1.txt
prefix_cats_oranges_2.txt
prefix_cats_oranges_3.txt
prefix_cats_tomatos_0.txt
prefix_cats_tomatos_1.txt
prefix_cats_tomatos_2.txt
prefix_cats_tomatos_3.txt
prefix_dogs_apples_0.txt
prefix_dogs_apples_1.txt
prefix_dogs_apples_2.txt
prefix_dogs_apples_3.txt
prefix_dogs_oranges_0.txt
prefix_dogs_oranges_1.txt
prefix_dogs_oranges_2.txt
prefix_dogs_oranges_3.txt
prefix_dogs_tomatos_0.txt
prefix_dogs_tomatos_1.txt
prefix_dogs_tomatos_2.txt
prefix_dogs_tomatos_3.txt

现在仅匹配满足您条件的文件并通过常规sort传递将产生:

$ find somedir/ -regextype posix-egrep -regex 'somedir/prefix_(cats|dogs)_(apples|oranges|tomatos).*[23].*$' | sort
somedir/prefix_cats_apples_2.txt
somedir/prefix_cats_apples_3.txt
somedir/prefix_cats_oranges_2.txt
somedir/prefix_cats_oranges_3.txt
somedir/prefix_cats_tomatos_2.txt
somedir/prefix_cats_tomatos_3.txt
somedir/prefix_dogs_apples_2.txt
somedir/prefix_dogs_apples_3.txt
somedir/prefix_dogs_oranges_2.txt
somedir/prefix_dogs_oranges_3.txt
somedir/prefix_dogs_tomatos_2.txt
somedir/prefix_dogs_tomatos_3.txt

由于您没有提供时间/日期在文件名中的位置的示例,因此按时间/日期进行的排序留给您。如果您还有其他问题,请告诉我。

答案 1 :(得分:1)

假设

  • 您的排序/过滤逻辑还可以
  • 您不需要递归搜索
  • 文件名中没有换行符

我会用这个:

printf '%s\n' someprefix_{cats,dogs}_{oranges,apples,tomatos}_[23]*.txt \
    | sort -t_ -k6 \
    | head -n $NUM_OF_FILES

这使用外壳程序的内置glob扩展功能来生成文件列表。每个结果都打印在单独的行上。使用与您的问题相同的管道处理输出。

答案 2 :(得分:-1)

与find函数匹配的默认正则表达式类型是Emacs正则表达式,因此模式的符号略有不同。

如果我正确理解了您的模式,则以下匹配命令有效:

find . '.*_\(cats\|dogs\)_\(oranges\|apples\|tomatos\)_\(2\|3\).*\.txt'

您可以找到有关emacs here的正则表达式类型和语法的任何信息。

希望有帮助