以下示例将目录中的所有文件与输入字符串($ string)进行比较并返回匹配的文件名。它不是一种非常优雅和有效的方法来实现这一目标。出于速度目的,我将for
条件修改为仅与以$ string的第一个单词开头的文件进行比较。
此脚本出现问题 - 目录中有两个文件:
Foo Bar.txt
Foo Bar Foo.txt
我将它们与字符串"Foo Bar 09.20.2010"
进行比较。这将返回该目录中的两个文件,因为两个文件都匹配。但我需要以最精确的方式返回与字符串匹配的文件 - 在我们的示例中,它应该是Foo Bar.txt
。
此外,如果你有更好的想法如何解决这个问题,请发表你的想法,因为我还没有那么精通脚本,我相信有更好的,甚至更简单的方法。
#!/bin/bash
string="Foo Bar 09.20.2010"
for file in /path/to/directory/$(echo "$string" | awk '{print $1}')*; do
filename="${file##*/}"
filename="${filename%.*}"
if [[ $(echo "$string" | grep -i "^$filename") ]]; then
result="$file"
echo $result
fi
done
这是我想要实现的细分。目录中的两个文件与两个字符串匹配,括号中的正确/不正确表示结果是否符合我的预期/想要。
目录中的2个文件(剥离扩展以进行匹配):
Foo Bar.txt
Foo Bar Foo.txt
与2个字符串进行比较:
Foo Bar Random Additional Text
Foo Bar Foo Random Additional Text
结果:
compare "Foo Bar"(.txt) against Foo Bar Random Additional Text -> Match (Correct)
compare "Foo Bar"(.txt) against Foo Bar Foo Random Additional Text -> Match (Incorrect)
compare "Foo Bar Foo"(.txt) against Foo Bar Random Additional Text -> NOT Match (Correct)
compare "Foo Bar Foo"(.txt) against Foo Bar Foo Random Additional Text -> Match (Correct)
谢谢大家的回答。
答案 0 :(得分:1)
如果我错了,请纠正我,但看起来你的脚本相当于:
ls /path/to/directory/"$string"*
如果您只想要一个文件名,则可以使用head
。由于ls
按字母顺序列出文件,因此您将按字母顺序排列第一个文件。
(请注意,当ls
的输出通过管道传输到另一个程序时,它会在每行打印一个文件名,这使得它比正常的基于列的输出更容易处理。)
ls /path/to/directory/"$string"* | head -1
对于最短匹配,请尝试以下内容,它使用awk
,sort -n
和cut
的笨拙组合来排序最短的行最长,然后打印第一个。
ls /path/to/directory/"$string"* |
awk '{print length($0) "\t" $0}' | sort -n | head -1 | cut -f 2-
答案 1 :(得分:0)
您的echo
和awk
电话很多都是多余的。要获得以匹配开头的所有文件,您只需评估“$ string”*即可。
e.g。两个
echo "$string"*
和
ls "$string"*
将生成您的列表。 (在管道中,echo将使它们以空格分隔,并且ls将使它们以换行符分隔。)
下一步是要意识到,鉴于此,正如您所定义的那样,“最精确匹配”的额外约束等同于最短的匹配文件名。
要在bash中找到一组字符串中的最短字符串(我自己更喜欢perl,但让我们坚持在bash中执行它的约束):
for fn in "/path/to/$string"*; do
echo $(echo $fn | wc -c) "$fn"
done | sort -n | head -1 | cut -f2- -d' '
for循环遍历扩展的文件名。 echo将名称的长度添加到名称之前。然后我们将其整个输出管道输入sort -n
和head -1
以获得最短的名称,并cut -f2- -d' '
去除它的长度(将第二个字段用空格作为字段分离器)。
shell编程的关键是了解你的构建块,以及如何组合它们。通过巧妙的排序,头部,尾部和切割组合,您可以进行许多非常复杂的处理。扔进sed和uniq,你已经能够做一些非常令人印象深刻的事情了。
话虽这么说,我通常只使用shell来实现这样的“动态” - 对于我可能想要重复使用的任何东西,这一切都很复杂我会更有可能使用的Perl。