我正在尝试编写一个简单的脚本,告诉我$ 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
但这不起作用。
答案 0 :(得分:8)
一种方法:
(
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*
扩展为 nothing 。 (没有它,它将保持不变。)( ... )
设置子shell,阻止shopt -s nullglob
“转义”。files=(/home/edward/bank1/fiche/Test*)
将文件列表放在名为files
的数组中。 (请注意,这仅在子shell中;在子shell退出后将无法访问files
。)"${#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
)
(此处( ... )
旨在阻止file
和found_file
“转义”。)
答案 1 :(得分:5)
您必须了解Unix 如何解释您的输入。
标准Unix shell在将参数传递给程序之前插入环境变量以及所谓的 globs 。这与Windows有点不同,它使程序解释扩展。
试试这个:
$ echo *
这将回显当前目录中的所有文件和目录。在echo
命令行动之前,shell会插入*
并展开它,然后将该扩展参数传递回您的命令。你可以通过这样做看到它:
$ set -xv
$ echo *
$ set +xv
set -xv
打开 xtrace 和详细。 Verbose回显输入的命令, xtrace 回显将要执行的命令(即shell扩展后)。
现在试试这个:
$ echo "*"
请注意,在引号内放置一些内容会隐藏shell中的 glob表达式,并且shell无法展开它。试试这个:
$ foo="this is the value of foo"
$ echo $foo
$ echo "$foo"
$ echo '$foo'
请注意,shell仍然可以在双引号内扩展环境变量,但不能在单引号中扩展。
现在让我们来看看你的陈述:
file="home/edward/bank1/fiche/Test*"
双引号阻止shell扩展 glob表达式,因此file
等于文字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
但是,如果有多个文件,您仍然可能会返回 found none 。相反,您可能会在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
命令有一个别名。试试这个:
$ ls -li /bin/test /bin/[
i
打印出 inode 。 inode 是文件的真实ID。具有相同ID的文件是相同的文件。您可以看到/bin/test
和/bin/[
是相同的命令。这使得以下两个命令相同:
if test -s $file
then
echo "The file exists"
fi
if [ -s $file ]
then
echo "The file exists"
fi
答案 2 :(得分:3)
您可以在一行中完成:
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世界中),boolean true是一个退出状态为0的程序。
ls
尝试列出模式,如果成功(意味着模式存在),则退出状态为0,否则为2(详情请参阅ls手册页)。
在我们的例子中,实际上有3个表达式,为了清楚起见,我将放括号,但不需要它们,因为&&
优先于||
:
(expression1 && expression2) || expression3
所以如果expression1为真(即:ls
找到了模式),它会计算表达式2(这只是一个回声并将以状态0退出)。在这种情况下,表达式3永远不会被评估,因为||
的左侧站点上的内容已经是真的,并且在尝试评估右侧的内容时会浪费资源。
否则,如果expression1为false,则不计算expression2,但在这种情况下,expression3为。
答案 3 :(得分:1)
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
答案 4 :(得分:0)
如果该脚本存在于指定的变量
中,以下脚本将帮助您转到进程cat > waitfor.csh
#!/bin/csh
while !( -e $1 )
sleep 10m
end
ctrl+D
此处-e
用于处理文件,
$1
是一个shell变量,
睡10分钟
你可以通过./waitfor.csh ./temp ; echo "the file exits"
答案 5 :(得分:0)
是否存在一个检查文件的衬垫 -
awk 'BEGIN {print getline < "file.txt" < 0 ? "File does not exist" : "File Exists"}'
答案 6 :(得分:-1)
通配符不会在引用的字符串中展开。当扩展通配符时,如果没有匹配则返回不变,它不会扩展为空字符串。尝试:
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 ]