我正在编写一个bash脚本,该脚本遍历某些目录中的所有文件,并且:
用于匹配文件的模式将传递给脚本,如下所示:
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。
答案 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的正则表达式类型和语法的任何信息。
希望有帮助