简体   繁体   English

Bash复合条件,带通配符和文件存在性检查

[英]Bash Compound Conditional, With Wildcards and File Existence Check

I've mastered the basics of Bash compound conditionals and have read a few different ways to check for file existence of a wildcard file, but this one is eluding me, so I figured I'd ask for help... 我已经掌握了Bash复合条件的基础知识,并且已经阅读了几种不同的方法来检查文件是否存在通配符文件,但是这个方法让我望而却步,所以我想我会请求帮助......

I need to: 1.) Check if some file matching a pattern exists AND 2.) Check that text in a different file exists. 我需要:1)检查一些文件匹配模式的存在和2)检查文本在不同的文件存在。

I know there's lots of ways to do this, but I don't really have the knowledge to prioritize them (if you have that knowledge I'd be interested in reading about that as well). 我知道有很多方法可以做到这一点,但我并没有真正的知识来优先考虑它们(如果你有这方面的知识,我也有兴趣阅读它)。

First things that came to mind is to use find for #1 and grep for #2 首先想到的是使用#1的#和#2的grep

So something like 所以像

if [ `grep -q "OUTPUT FILE AT STEP 1000" ../log/minimize.log` ] \
      && [ `find -name "jobscript_minim\*cmd\*o\*"` ]; then
   echo "Both passed! (1)"
fi

That fails, though curiously: 虽然好奇但是失败了:

if `grep -q "OUTPUT FILE AT STEP 1000" ../log/minimize.log` ;then
   echo "Text passed!"
fi
if `find -name "jobscript_minim\*cmd\*o\*"` ;then
   echo "File passed!"
fi

both pass... 都通过......

I've done a bit of reading and have seen people talking about the problem of multiple filenames matching wildcards within an if statement. 我已经做了一些阅读,并且看到人们在if语句中讨论了匹配通配符的多个文件名的问题。 What's the best solution to this? 什么是最好的解决方案? (in answer my question, I'd assumed you take a crack at that question, as well, in the process) (在回答我的问题时,我假设你在这个过程中对这个问题采取了一个解决方案)

Any ideas/solutions/suggestions? 任何想法/解决方案/建议?

Let's tackle why your attempt failed first: 让我们先解决你的尝试失败的原因:

if [ `grep -q …` ]; 

This runs the grep command between backticks, and interpolates the output inside the conditional command. 这将在反引号之间运行grep命令,并在条件命令内插入输出。 Since grep -q doesn't produce any output, it's as if you wrote if [ ]; 因为grep -q不会产生任何输出,所以就好像你写了if [ ];

The conditional is supposed to test the return code of grep , not anything about its output. 条件应该测试grep的返回代码,而不是关于其输出的任何内容。 Therefore it should be simply written as 因此,应该简单地写成

if grep -q …;

The find command returns 0 (ie true) even if it finds nothing, so this technique won't work. find命令返回0(即true),即使它什么都没找到,所以这种技术不起作用。 What will work is testing whether its output is empty, by collecting its output any comparing it to the empty string: 什么工作是测试它的输出是否为空,通过收集它的输出任何比较它与空字符串:

if [ "$(find …)" != "" ];

(An equivalent test is if [ -n "$(find …)" ] .) (等效测试是if [ -n "$(find …)" ] 。)

Notice two things here: 请注意两件事:

  • I used $(…) rather than backticks. 我使用$(…)而不是反引号。 They're equivalent, except that backticks require strange quoting inside them (especially if you try to nest them), whereas $(…) is simple and reliable. 它们是等效的,除了反引号需要在它们内部引用奇怪的引用(特别是如果你试图嵌套它们),而$(…)是简单可靠的。 Just use $(…) and forget about backticks (except that you need to write \\` inside double quotes). 只需使用$(…)而忘记了反引号(除非你需要编写\\`双引号)。

  • There are double quotes around $(…) . $(…)附近有双引号。 This is really important. 这非常重要。 Without the quotes, the shell would break the output of the find command into words. 如果没有引号,shell会将find命令的输出分解为单词。 If find prints, say, two lines dir/file and dir/otherfile , we want if [ "dir/file dir/otherfile" = "" ]; 如果find打印,比如两行dir/filedir/otherfile ,我们想要if [ "dir/file dir/otherfile" = "" ]; to be executed, not if [ dir/file dir/otherfile = "" ]; 要执行,而不是if [ dir/file dir/otherfile = "" ]; which is a syntax error. 这是一个语法错误。 This is a general rule of shell programming: always put double quotes around a variable or command substitution . 这是shell编程的一般规则: 总是在变量或命令替换周围加上双引号 (A variable substitution is $foo or ${foo} ; a command substitution is $(command) .) (变量替换是$foo${foo} ;命令替换是$(command) 。)


Now let's see your requirements. 现在让我们看看你的要求。

  1. Check if some file matching a pattern exists 检查是否存在与模式匹配的文件

    If you're looking for files in the current directory or in any directory below it recursively, then find -name "PATTERN" is right. 如果您在当前目录或递归下面的任何目录中查找文件,则find -name "PATTERN"是正确的。 However, if the directory tree can get large, it's inefficient, because it can spend a lot of time printing all the matches when we only care about one. 但是,如果目录树可能变得很大,那么效率很低,因为当我们只关心一个匹配时,它会花费大量时间打印所有匹配。 An easy optimization is to only retain the first line by piping into head -n 1 ; 一个简单的优化是只通过管道保留第一条线head -n 1 ; find will stop searching once it realizes that head is no longer interested in what it has to say. find将停止搜索,一旦它意识到head已不再感兴趣,它有什么可说的。

    if [ "$(find -name "jobscript_minim cmd o" | head -n 1)" != "" ]; if [“$(find -name”jobscript_minim cmd o“| head -n 1)”!=“”];

    (Note that the double quotes already protect the wildcards from expansion.) (请注意,双引号已经保护通配符不受扩展。)

    If you're only looking for files in the current directory, assuming you have GNU find (which is the case on Linux, Cygwin and Gnuwin32), a simple solution is to tell it not to recurse deeper than the current directory. 如果您只是在当前目录中查找文件,假设您有GNU查找(Linux,Cygwin和Gnuwin32就是这种情况),一个简单的解决方案就是告诉它不要比当前目录更深入。

    if [ "$(find -maxdepth 1 -name "jobscript_minim*cmd*o*")" != "" ]; if [“$(find -maxdepth 1 -name”jobscript_minim * cmd * o *“)”!=“”];

    There are other solutions that are more portable, but they're more complicated to write. 还有其他更便携的解决方案,但写入起来更复杂。

  2. Check that text in a different file exists. 检查其他文件中是否存在文本。

    You've already got a correct grep command. 你已经有了正确的grep命令。 Note that if you want to search for a literal string, you should use grep -F ; 请注意,如果要搜索文字字符串,则应使用grep -F ; if you're looking for a regexp, grep -E has a saner syntax than plain grep . 如果你正在寻找一个正则表达式,那么grep -E的语法比普通的grep要好。

Putting it all together: 把它们放在一起:

if grep -q -F "OUTPUT FILE AT STEP 1000" ../log/minimize.log &&
   [ "$(find -name "jobscript_minim*cmd*o*")" != "" ]; then
  echo "Both passed! (1)"
fi

bash 4 bash 4

shopt -s globstar
files=$(echo **/jobscript_minim*cmd*o*)
if grep -q "pattern" file && [[ ! -z $files ]];then echo "passed"; fi
for i in filename*; do FOUND=$i;break;done
if [ $FOUND == 'filename*' ]; then
echo “No files found matching wildcard.”
else
echo “Files found matching wildcard.”
fi

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM