![用于模式搜索和列出目录中文件的 shell 脚本](https://linux22.com/image/190935/%E7%94%A8%E4%BA%8E%E6%A8%A1%E5%BC%8F%E6%90%9C%E7%B4%A2%E5%92%8C%E5%88%97%E5%87%BA%E7%9B%AE%E5%BD%95%E4%B8%AD%E6%96%87%E4%BB%B6%E7%9A%84%20shell%20%E8%84%9A%E6%9C%AC.png)
我曾经使用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)*