我正在尝试编写一个简单的脚本,告诉我$ 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)
但这不起作用.
一种方法:
(
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"逃避".)
您必须了解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)
| 归档时间: |
|
| 查看次数: |
110683 次 |
| 最近记录: |