我需要检查一个目录(我们称之为dir)是否包含两个文件之一(我们称之为filea和fileb),但既不包含一个文件,也不包含两个文件。
理想的解决方案是在谓词之间使用 XOR 运算:
if [ -f dir/filea ] ^ [ -f dir/fileb]
then
echo Structure ok
# do stuff
fi
Run Code Online (Sandbox Code Playgroud)
然而,shell 不支持^作为 XOR 运算符,并且该[命令没有选项-X或--xor像它那样具有-aand -o...使用否定相等也不起作用:
if ! [ -f dir/filea -eq -f dir/fileb ]
# or
if ! [ -f dir/filea = -f dir/fileb ]
Run Code Online (Sandbox Code Playgroud)
有没有什么方法可以实现这一点,而不需要求助于像这样的成熟的 AND/OR 表达式
if { [ -f dir/filea ] || [ -f dir/fileb ]; } && ! …Run Code Online (Sandbox Code Playgroud) 问题:我需要检查今天是否是星期四并根据此条件的结果执行不同的操作。我尝试了两种不同的方法:
DAYOFWEEK=$(date +"%a")
echo DAYOFWEEK: $DAYOFWEEK
if ["$DAYOFWEEK" == "Thu"];
then
echo YES
else
echo NO
fi
Run Code Online (Sandbox Code Playgroud)
DAYOFWEEK=$(date +"%u")
echo DAYOFWEEK: $DAYOFWEEK
if ["$DAYOFWEEK" == 4];
then
echo YES
else
echo NO
fi
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,输出都是 NO,即使它应该是 YES。怎么了?
斯蒂芬·查泽拉斯写道:
一些规则,如
- 总是引用变量
- 永远不要使用
-aor-o运算符(使用多个[命令和&&and||shell 运算符)请
[与POSIX壳可靠。
为什么“永远不要使用-aor-o运算符”?
我怎样才能“使用多个[命令&&和||shell 运算符)”?
什么是首选
if ! [ ... ]; then
Run Code Online (Sandbox Code Playgroud)
和
if [ ! ... ]; then
Run Code Online (Sandbox Code Playgroud)
实际上它们的结果相同,是否有首选语法?在前一种语法中,评估的 not 是 shell 内置的,而在后者中, not 是test一个,这有什么区别吗?
如果我以非特权用户的身份创建一个文件,并将权限模式更改为400,则该用户正确地将其视为只读:
$ touch somefile
$ chmod 400 somefile
$ [ -w somefile ] && echo rw || echo ro
ro
Run Code Online (Sandbox Code Playgroud)
一切都很好。
但后来 root 出现了:
# [ -w somefile ] && echo rw || echo ro
rw
Run Code Online (Sandbox Code Playgroud)
有没有搞错?当然,root 可以写入只读文件,但它不应该养成这样的习惯:最佳实践往往会规定我应该能够测试写权限位,如果不是,则已设置那样是有原因的。
我想我想了解为什么会发生这种情况,以及在测试没有设置写入位的文件时如何获得错误的返回码?
内置test和[实用程序在大多数 shell 中都有-nt("newer than") 和-ot("older than") 测试,即使 shell 以“POSIX 模式”运行(对于同名的外部实用程序也是如此)我可以访问的系统)。这些测试用于比较两个文件的修改时间戳。它们记录的语义在不同的实现中略有不同(关于如果一个或另一个文件不存在会发生什么),但它们未包含在POSIX 规范中。为test实用程序。
他们不结转到
test时,从[KornShell]壳去除有条件的命令,因为他们没有被列入工具test内置于历史实现实用sh工具。
假设我想比较/bin/shshell 脚本中文件之间的修改时间戳,然后根据一个文件是否比另一个文件新来采取行动,如
if [ "$sigfile" -nt "$timestamp" ] ||
[ "$sigfile.tmp" -nt "$timestamp" ]
then
return
fi
Run Code Online (Sandbox Code Playgroud)
...除了make(至少可以说脚本的其余部分变得笨拙)之外,我还可以使用什么其他实用程序?或者我应该假设没有人会在“历史实现sh”上运行脚本,或者辞职为特定的shell编写,例如bash?
多年来,我多次遇到变量与字符串文字的比较,其中在变量和文字前有一个字符,例如
if [ "x$A" = "xtrue" ]; then
Run Code Online (Sandbox Code Playgroud)
为了检查是否$A是"true"。
我认为这样做是为了实现 shell 兼容性或解决长期错误、不直观的行为等。没有什么明显的想法。
今天我想我想知道原因,但我的研究没有任何结果。或者也许只是我在频繁接触罕见事件中有所作为。
这种做法是否仍然有用,甚至是最好的?
作为一名主要的 Java 程序员,我发现 bash if-then构造非常令人困惑,尤其是在空格方面。谁能解释为什么第一个有效,而第二个或第三个无效?
#works
if [ -n $1 ]; then echo "parameterized"; fi
#output: ./links: Zeile 1: [-n: Kommando nicht gefunden.
if [-n $1 ]; then echo "parameterized"; fi
#output: ./links: Zeile 1: [: Fehlende `]'
if [ -n $1]; then echo "parameterized"; fi
Run Code Online (Sandbox Code Playgroud) 我有一个名为“teleport.sh”的 shell 脚本,如下所示:
if [ $1="1" ];
then
shift
mv "$@" ~/lab/Sun
elif [ $1="2" ];
then
shift
mv "$@" ~/lab/Moon
elif [ $1="3" ];
then
shift
mv "$@" ~/lab/Earth
fi
Run Code Online (Sandbox Code Playgroud)
当我执行:
sh teleport.sh 2 testfile
Run Code Online (Sandbox Code Playgroud)
这testfile被移动到~/lab/Sun目录中,这让我很困惑,因为我没有将 1 或 '1' 传递给该脚本。
这里有什么问题?
我从指令中阅读了在本月最后一天安排脚本的说明:
注意:
精明的读者可能想知道如何设置命令在每个月的最后一天执行,因为您无法将 dayofmonth 值设置为涵盖每个月。这个问题一直困扰着 Linux 和 Unix 程序员,并产生了很多不同的解决方案。一种常用的方法是添加一个 if-then 语句,该语句使用 date 命令来检查明天的日期是否为 01:Run Code Online (Sandbox Code Playgroud)00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1这会在每天中午 12 点检查是否是该月的最后一天,如果是,则 cron 运行该命令。
如何[`date +%d -d tomorrow` = 01 ]工作?
陈述正确then; command1吗?
test ×10
shell ×7
bash ×3
date ×2
shell-script ×2
cron ×1
filenames ×1
files ×1
permissions ×1
posix ×1
readonly ×1
string ×1
timestamps ×1
variable ×1
whitespace ×1