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

Edw*_*ard 8 shell

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

例如,我有这些文件

Test1989.txt
Test1990.txt
Test1991.txt
Run Code Online (Sandbox Code Playgroud)

然后我只想回应一个文件被发现.

例如,像这样:

file="home/edward/bank1/fiche/Test*"
if  test -s "$file" 
then 
    echo "found one"
else 
    echo "found none"
fi
Run Code Online (Sandbox Code Playgroud)

但这不起作用.

rua*_*akh 8

一种方法:

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

说明:

  • shopt -s nullglob如果没有文件匹配该模式,将导致/home/edward/bank1/fiche/Test*扩展为空.(没有它,它将保持不变.)
  • ( ... )设置子shell,防止shopt -s nullglob"转义".
  • files=(/home/edward/bank1/fiche/Test*)将文件列表放在一个名为的数组中files.(请注意,这仅在子shell中; files在子shell退出后将无法访问.)
  • "${#files[@]}" 是此数组中的元素数.

编辑以解决后续问题("如果我还需要检查这些文件中是否有数据并且不是零字节文件,那该怎么办"):

对于这个版本,我们需要使用-s(正如你在你的问题中所做的那样),它也测试文件的存在,所以没有必要再使用shopt -s nullglob了:如果没有文件匹配模式,那么-s模式将是假的.所以,我们可以写:

(
  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
)
Run Code Online (Sandbox Code Playgroud)

(这里( ... )是为了防止file和found_file"逃避".)


Dav*_* W. 6

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

标准的Unix shell 会在将参数传递给程序之前插入环境变量以及所谓的globs.这与Windows有点不同,这使得程序解释了扩展.

试试这个:

 $ echo *
Run Code Online (Sandbox Code Playgroud)

这将回显当前目录中的所有文件和目录.在echo命令执行操作之前,shell *会对其进行插值并展开,然后将该扩展参数传递回命令.你可以通过这样做看到它的实际效果:

$ set -xv
$ echo *
$ set +xv
Run Code Online (Sandbox Code Playgroud)

在set -xv上回合X跟踪和详细.详细回显输入的命令,并且xtrace回显将要执行的命令(即,在shell扩展之后).

现在试试这个:

$ echo "*"
Run Code Online (Sandbox Code Playgroud)

请注意,在引号内放置一些内容会从shell中隐藏glob表达式,而shell无法展开它.试试这个:

$ foo="this is the value of foo"
$ echo $foo
$ echo "$foo"
$ echo '$foo'
Run Code Online (Sandbox Code Playgroud)

请注意,shell仍然可以在双引号内扩展环境变量,但不能在单引号中扩展.

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

file="home/edward/bank1/fiche/Test*"
Run Code Online (Sandbox Code Playgroud)

双引号阻止shell扩展glob表达式,因此file等于文字home/edward/bank1/finche/Test*.因此,您需要这样做:

file=/home/edward/bank1/fiche/Test*
Run Code Online (Sandbox Code Playgroud)

缺少引号(以及重要的介绍性斜杠!)现在将使文件等于与该表达式匹配的所有文件.(可能不止一个!).如果没有文件,取决于shell及其设置,shell可能只是将文件设置为该文字字符串.

你当然有正确的想法:

 file=/home/edward/bank1/fiche/Test*
 if  test -s $file
    then 
        echo "found one"
    else 
       echo "found none"
 fi
Run Code Online (Sandbox Code Playgroud)

但是,如果有多个文件,您仍然可能无法返回.相反,您可能会在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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我正在利用ls命令的退出代码.如果ls找到一个可以访问的文件,它将返回零退出代码.如果找不到一个匹配的文件,则返回非零退出代码.该if命令仅执行命令,然后如果该命令返回零,则它将该if语句假定为true并执行该if子句.如果该命令返回非零值,if则假定该语句为false,并执行该else子句(如果有的话).

该test命令以类似的方式工作.如果test为true,则该test命令返回零.否则,该test命令返回非零值.这对if命令很有用.事实上,有一个别名的test命令.试试这个:

 $ ls -li /bin/test /bin/[
Run Code Online (Sandbox Code Playgroud)

在i打印出的inode.该索引节点是该文件的真实身份.具有相同ID的文件是相同的文件.你可以看到它/bin/test并且/bin/[是相同的命令.这使得以下两个命令相同:

if test -s $file
then
    echo "The file exists"
fi

if [ -s $file ]
then
    echo "The file exists"
fi
Run Code Online (Sandbox Code Playgroud)


Bar*_*mar -1

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

output="$(ls home/edward/bank1/fiche/Test* 2>/dev/null)"
if [ -n "$output" ]
then echo "Found one"
else echo "Found none"
fi
Run Code Online (Sandbox Code Playgroud)

如果通配符扩展为文件名,ls会将它们列在stdout; 否则它将在 上打印错误stderr,并且在标准输出上不打印任何内容。的内容stdout被分配给output。

if [ -n "$output" ]测试是否$output包含任何东西。

另一种写法是:

if [ $(ls home/edward/bank1/fiche/Test* 2>/dev/null | wc -l) -gt 0 ]
Run Code Online (Sandbox Code Playgroud)