用于模式搜索和列出目录中文件的 shell 脚本

用于模式搜索和列出目录中文件的 shell 脚本

我曾经使用ls | agrep "<search pattern #1>;<search pattern #2>;...;<search pattern #n>"某些搜索模式快速和/或有效地执行目录中某些文件的搜索/列表。作为说明,我创建了一个空目录,并使用touch以下命令填充了一些空文件:

~ ls -l
total 0
-rw-r--r-- 1 me users 0 May  7 14:00 animals-bird_dog_cat.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-bird_dog.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-bird.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-cat_dog_bird.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-cat_dog.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-cat.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-dog_bird.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-dog_cat_bird.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-dog_cat.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-dog.txt

然后,使用ls -l | agrep "cat;bird",我可以毫无问题地搜索/查找名称仅包含的文件如下所示。

~ ls -l | agrep 'cat;bird'
-rw-r--r-- 1 me users 0 May  7 14:00 animals-bird_dog_cat.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-cat_dog_bird.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-dog_cat_bird.txt

AFAICT,这种方法非常快速且有效(我洗耳恭听更好的解决方案)。由于我每天都会做很多这样的事情,因此我认为最好编写一个简单的 shell 脚本来通过简单地在 CLI 中给出搜索模式来执行此类任务。例如,我编写了一个简单的 shell 脚本,如下所示,并将其命名mls并使其可执行:

#!/bin/bash
bold=$(tput bold)
italic=$(tput sitm)
normal=$(tput sgr0)
if [ "$#" -lt 1 ]; then
    echo "${bold}Usage${normal}: $0 <search string 0> [... <search string n>]"
    exit 0
fi
patterns=""
for ((i=1;i<$#;i++))
do
    patterns+="${!i};"
done
patterns+="${!#}"
/usr/bin/ls -lart | agrep '${patterns}${!#}'

然后,当我使用搜索模式 执行上述 shell 脚本时mls cat bird,它什么也没有返回,如下所示。

~ ls -l | agrep 'cat;bird'
-rw-r--r-- 1 me users 0 May  7 14:00 animals-bird_dog_cat.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-cat_dog_bird.txt
-rw-r--r-- 1 me users 0 May  7 14:00 animals-dog_cat_bird.txt
~ mls cat bird
~

我错过了什么?

答案1

您可以切换到zsh这里,其 glob 支持 OR、AND(以及 AND-NOT 和 NOT)和近似

$  set -o extendedglob # best in ~/.zshrc
$ ls -ld -- (#a1)*dig*~^(#a1)*bard*
-rw-rw-r-- 1 chazelas chazelas 0 May  8 16:24 animals-bird_dog_cat.txt
-rw-rw-r-- 1 chazelas chazelas 0 May  8 16:24 animals-bird_dog.txt
-rw-rw-r-- 1 chazelas chazelas 0 May  8 16:24 animals-cat_dog_bird.txt
-rw-rw-r-- 1 chazelas chazelas 0 May  8 16:24 animals-dog_bird.txt
-rw-rw-r-- 1 chazelas chazelas 0 May  8 16:24 animals-dog_cat_bird.txt

答案2

除了单引号问题之外,您还将最后一个元素添加两次

patterns+="${!#}"
/usr/bin/ls -lart | agrep "${patterns}${!#}"

运行程序可以bash -x mls cat bird看到


但您不需要循环:"$*"特殊参数使用 IFS 的第一个字符连接位置参数。如果我们临时为 IFS 定义一个新值,我们可以这样做

patterns=$( IFS=';'; echo "$*" )

如果您不需要 的“近似”部分agrep,bash 可以使用以下命令自行完成此操作扩展的全局模式

pattern=$( IFS='|'; echo "$*" )
shopt -s extglob
ls *@($pattern)*

相关内容