用于检查文件是否存在的Shell脚本

用于检查文件是否存在的Shell脚本,shell,Shell,我试图编写一个简单的脚本,告诉我$Temp中是否存在以字符串“Test”开头的文件名 例如,我有这些文件 Test1989.txt Test1990.txt Test1991.txt 然后我只想回显找到了一个文件 例如,类似这样的内容: file="home/edward/bank1/fiche/Test*" if test -s "$file" then echo "found one" else echo "found none" fi 但这不起作用。通配符不会在

我试图编写一个简单的脚本,告诉我$Temp中是否存在以字符串“Test”开头的文件名

例如,我有这些文件

Test1989.txt
Test1990.txt
Test1991.txt
然后我只想回显找到了一个文件

例如,类似这样的内容:

file="home/edward/bank1/fiche/Test*"
if  test -s "$file" 
then 
    echo "found one"
else 
    echo "found none"
fi

但这不起作用。

通配符不会在带引号的字符串中展开。当扩展通配符时,如果没有匹配项,则返回原样,它不会扩展为空字符串。尝试:

output="$(ls home/edward/bank1/fiche/Test* 2>/dev/null)"
if [ -n "$output" ]
then echo "Found one"
else echo "Found none"
fi
如果通配符扩展为文件名,
ls
将在
stdout
上列出它们;否则,它将在stderr上打印错误,而在stdout上不打印任何内容。
stdout
的内容分配给
output

if[-n“$output”]
测试
$output
是否包含任何内容

另一种写法是:

if [ $(ls home/edward/bank1/fiche/Test* 2>/dev/null | wc -l) -gt 0 ]
一种方法:

(
  shopt -s nullglob
  files=(/home/edward/bank1/fiche/Test*)
  if [[ "${#files[@]}" -gt 0 ]] ; then
    echo found one
  else
    echo found none
  fi
)
说明:

  • shopt-s nullglob
    将导致
    /home/edward/bank1/fiche/Test*
    在没有与该模式匹配的文件的情况下展开为空。(没有它,它将完好无损。)
  • (…)
    设置子shell,防止
    shopt-s nullglob
    进行“转义”
  • files=(/home/edward/bank1/fiche/Test*)
    将文件列表放入名为
    files
    的数组中。(请注意,这仅在子shell中;
    文件在子shell退出后将无法访问。)
  • “${#files[@]}”
    是此数组中的元素数


编辑以解决后续问题(“如果我还需要检查这些文件中是否包含数据且不是零字节文件怎么办”):

对于这个版本,我们需要使用
-s
(正如您在问题中所做的那样),它还测试文件的存在性,因此不再使用
shopt-s nullglob
了:如果没有文件与模式匹配,那么模式上的
-s
将为false。因此,我们可以写:

(
  found_nonempty=''
  for file in /home/edward/bank1/fiche/Test* ; do
    if [[ -s "$file" ]] ; then
      found_nonempty=1
    fi
  done
  if [[ "$found_nonempty" ]] ; then
    echo found one
  else
    echo found none
  fi
)

(此处,
(…)
用于防止
文件和
找到的文件
被“转义”。

您可以在一行中执行此操作:

ls /home/edward/bank1/fiche/Test* >/dev/null 2>&1 && echo "found one" || echo "found none"
要理解它是什么,您必须分解命令并对布尔逻辑有基本的了解

直接从bash手册页:

[...]
expression1 && expression2
     True if both expression1 and expression2 are true.
expression1 || expression2
     True if either expression1 or expression2 is true.
[...]
在shell中(通常在unix世界中),布尔值true是一个状态为0的程序

ls
尝试列出模式,如果成功(意味着该模式存在),则退出状态为0,否则退出状态为2(有关详细信息,请查看ls手册页)

在我们的例子中,实际上有3个表达式,为了清楚起见,我将插入括号,尽管它们不是必需的,因为
&&
优先于
|

 (expression1 && expression2) || expression3
因此,如果expression1为true(即:
ls
找到模式),它将计算expression2(它只是一个回显,将以状态0退出)。在这种情况下,expression3永远不会被评估,因为
|
左侧站点上的内容已经是真实的,尝试评估右侧的内容将是一种资源浪费


否则,如果expression1为false,则不计算expression2,但在本例中,expression3为。

您必须了解Unix如何解释您的输入

标准unixshell在将参数传递给程序之前插入环境变量以及称为globs的变量。这与Windows有点不同,Windows让程序解释扩展

试试这个:

 $ echo *
$ foo="this is the value of foo"
$ echo $foo
$ echo "$foo"
$ echo '$foo'
 $ ls -li /bin/test /bin/[
这将回显当前目录中的所有文件和目录。在
echo
命令执行之前,shell将插入
*
并展开它,然后将展开的参数传递回您的命令。通过执行以下操作,您可以看到它正在运行:

$ set -xv
$ echo *
$ set +xv
set-xv
打开xtrace和verbose。Verbose回显输入的命令,xtrace回显将要执行的命令(即,在shell扩展之后)

现在试试这个:

$ echo "*"
请注意,将某些内容放在引号中会对shell隐藏glob表达式,并且shell无法展开它。试试这个:

$ foo="this is the value of foo"
$ echo $foo
$ echo "$foo"
$ echo '$foo'
 $ ls -li /bin/test /bin/[
请注意,shell仍然可以在双引号内展开环境变量,但不能在单引号内展开

现在让我们看看你的陈述:

file="home/edward/bank1/fiche/Test*"
双引号阻止shell扩展glob表达式,因此
file
等于literal
home/edward/bank1/finche/Test*
。因此,您需要执行以下操作:

file=/home/edward/bank1/fiche/Test*
缺少引号(以及重要的介绍性斜杠!)将使文件等于所有匹配该表达式的文件。(可能不止一个!)。如果没有文件,取决于shell及其设置,shell可能只是简单地将文件设置为该文本字符串

你肯定有正确的想法:

 file=/home/edward/bank1/fiche/Test*
 if  test -s $file
    then 
        echo "found one"
    else 
       echo "found none"
 fi
但是,如果有多个文件,您仍然可能会发现未返回任何文件。相反,您的
test
命令可能会出错,因为参数太多

解决这一问题的一种方法可能是:

if ls /home/edward/bank1/finche/Test* > /dev/null 2>&1
then
    echo "There is at least one match (maybe more)!"
else
    echo "No files found"
fi
在本例中,我利用了
ls
命令的退出代码。如果
ls
找到一个可以访问的文件,则返回零退出代码。如果找不到匹配的文件,则返回非零退出代码。
if
命令仅执行一个命令,然后如果该命令返回零,它将假定
if
语句为true,并执行
if
子句。如果命令返回非零值,则假定
If
语句为false,并执行
else
子句(如果有)

test
命令的工作方式类似。如果
test
为真,则
test
命令返回零。否则,
test
命令将返回一个非零值。这对于
if
命令非常有效。实际上,
test
命令有一个别名。尝试
for entry in "/home/loc/etc/"/*
do

   if [ -s /home/loc/etc/$entry ]
   then
       echo "$entry File is available"
   else
       echo "$entry File is not available"
fi
done

Hope it helps
awk 'BEGIN {print getline < "file.txt" < 0 ? "File does not exist" : "File Exists"}'