ksh 中的反引号内的引号

ksh 中的反引号内的引号

我试图在 HP-UX Unix 中使用以下命令获取当前日期的文件:

$ ls -lrt ABC.LOG* |grep "`date +"%b %d"`"

但是,它给了我错误:

ksh: : cannot execute
grep: can't open %d

有什么建议么?

答案1

该错误源于对参数的引用grep以及反引号不能很好地进行嵌套这一事实:

grep "`date +"%b %d"`"

这更好地写成

grep "`date +'%b %d'`"

...或者甚至更好,

grep "$(date +'%b %d')"

事实上,$(...)您应该能够保留内部双引号,而不是反引号:

grep "$(date +"%b %d")"

grep 输出的另一种选择ls

find . -type f -name "ABC.LOG*" -ctime -1

这将找到-type f当前目录中名称与给定模式匹配且 ctime 为的所有常规文件 ( )自当前时间起不到 24 小时。文件的 ctime 是最后一次修改文件数据或元数据的时间。

但这并不完全等同于您想要实现的目标。这也会递归到子目录中。

答案2

在 Korn shell 中,就像在 Bourne shell 中一样,引号和反引号(命令替换的古老形式)可能是不匹配的,您必须帮助标记器来判断反引号在哪里结束。反引号内部还有另一级反斜杠处理。

echo "`date"

有效并且与以下相同:

echo "`date`"
echo "$(date)"

和:

echo `echo "foo`

有效并且与以下相同:

echo `echo "foo"`
echo $(echo "foo")

如果你这样做:

grep "`date +"%b %d"`"

这被视为一个grep单词,然后("`date +"双引号内未闭合的反引号)与双引号内的另一个未闭合反引号: 连接。所以就像%b%d"`"

grep "$(date +)"%b %d"$()"

(除了由于某种原因,虽然echo "``"echo "$()"不会导致错误,但在 中echo "`",shell 将尝试执行具有空名称的命令(就像您编写了echo "$("")")。

所以在这里,你需要使用反斜杠来帮助解析器:

grep "`date +\"%b %d\"`"

这些反斜杠实际上已被删除。它是date +"%b %d"由命令替换中的子 shell 进行评估的。

在这里,由于ksh接受未闭合的引号,您实际上也可以这样做:

grep "`date +\"%b %d"

(并不是说我建议这样做)。

这也是获得嵌套反引号的方法,如下所示:

echo "`echo \"\`echo \\\"a  b\\\"\`\"`"

一个很好的例子,为什么很少有人使用该语法并使用较新的形式(在 80 年代初$(...)引入):ksh

echo "$(echo "$(echo "a  b")")"

现在,对于您的特定问题,您似乎想要列出ABC.LOG*当前目录中今天最后修改的文件。为此,你可以这样做:

touch -t "$(date +%Y%m%d0000)" .start-of-day &&
  find . ! -name . -prune -name 'ABC.LOG.*' \
    -newer .start-of-day -type f -exec ls -lrtd {} + &&
  rm -f .start-of-day

答案3

find命令可用于正确的工具,而不是 dolsgreping 结果,因此请注意不解析ls结果

find /path/to/ -type f -name "ABC.LOG*$(date +"%b %d")*"

上面是查找今天的日期文件名,如果您正在查找今天创建/修改的文件,您可以find这样使用(GNU 版本find):

find /path/to -type f -name "ABC.LOG*" -newermt 00:00

或者在过去 24 小时内:

find /path/to -type f -name "ABC.LOG*" -newermt yesterday

或者如下:

find /path/to -type f -name "ABC.LOG*" -newermt "$(date +"%b %d")"

相关内容