当使用变量而不是硬编码文件名时调查 bash 脚本中的差异错误

Investigating a diff error in a bash script when variables are used instead of hardcoded file names

我有一个脚本可以在指定目录中查找特定类型的文件,如果它们存在,则在创建 tar.gz 之前生成一个具有基本名称的文件。压缩后,我通过 运行 差异检查检查以确保 tarball 包含所有文件。

我创建了一对变量,它们是预压缩文件列表和 tarball 中的变量。当我 运行 包含 diff 变量的 if 语句时,我收到此错误:

diff: missing operand after `/my/original/dir/filelist.txt'
diff: Try `diff --help' for more information. 

我通过引用文件本身而不是创建的变量来解决这个问题。如果我在单独的 bash 脚本中 运行 if 语句,它使用变量就可以正常工作,所以我完全不知道我的较大脚本中的错误是什么。下面我提供了大脚本的片段和 diff 语句作为其自己的脚本以供参考。

它自己的脚本中的 if 差异:

#!/bin/sh
filelist=(filelist.txt)
tarfiles=(tarfiles.txt)
#differences=$(diff filelist.txt tarfiles.txt) #Uncomment if below fails
differences=$(diff $filelist $tarfiles)
if $differences > /dev/null ; then  
  echo Same
else
  echo Different
fi

以上工作正常。

现在把这个放在我更大的脚本的末尾:

TARFILES=$(tar -tzf "$ARCHIVES/tarredfiles.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' > $LOGS/tarfiles.txt)

FILELIST=($LOGS/filelist.txt)

#Check to see if it all worked

DIFF=$(diff $FILELIST $TARFILES)    

cd $LOGS #I shouldn't need to do this but I do as a safety mechanism

#if diff filelist.txt tarfiles.txt > /dev/null ; then

if diff $FILELIST $TARFILES > /dev/null ; then
    echo "Today's files have been archived and checked."
else
    echo "Some or none of today's files have been archived, check the logs to find the error."
    echo (diff $TARFILES $FILELIST) > $LOGS/$(date '+%Y%m%d')errors.txt

fi

我试过将变量括在 "" 中,但似乎没有什么不同。

填充 TARFILES 的方式导致它为空。您要在变量中存储什么?

这一行

TARFILES=$(tar -tzf "$ARCHIVES/tarredfiles.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' > $LOGS/tarfiles.txt)

是否进行以下步骤

  • 从名为 [=19] 的压缩 (-z) tar 文件 (-f) 中提取文件名 (-t) 列表=]在$ARCHIVES变量

  • 引用的目录中
  • 将文件名列表发送(管道)到 awk 中,在那里打印文件名的最后一个部分,即每行的最后一个字段($NF)它被 / (-F/)

  • 分割
  • 将所有输出发送(重定向)到日志文件中 $LOGS/tarfiles.txt

  • 捕获任何其他输出(其中将有 none!)并将其存储在 TARFILES 变量中。

所以,变量 TARFILES总是空的,但是文件 tarfiles.txt里面有内容.

您似乎希望 difftarfiles.txt 的内容与 filelist.txt 的内容进行比较,但您尝试以一种不真的很符合那个。

形式的表达式:

TARFILES=$( command goes here )

捕获该命令的输出

TARFILES=$( command goes here > some-file.txt )

将命令的输出发送到文件中,然后捕获 nothing.

你想要的是这样的:

TARFILES=some-file.txt
command goes here > $TARFILES

这会将变量设置为文件的 名称 ,然后 运行 将内容放入该文件的命令。

所以,具体来说:

TARFILES=$LOGS/tarfiles.txt
tar -tzf "$ARCHIVES/tarredfiles.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' > $TARFILES

当工作将 shell 脚本时,运行ning 命令产生的输出进入文件等是很常见的。有一件事你需要在逻辑上真正清楚当您希望您的变量包含实际内容(即命令的 输出 )以及当您希望它们包含文件名时。

在您的情况下,您想要 运行 比较恰好包含文件名列表的 2 个文件("tarfiles" 和 "filelist"),这意味着还有更多跟踪,但本质上你想用命令的输出填充 "tarfiles",然后 运行 一个差异,你在其中传递 2 个文件名 "tarfiles" 和 "filelist".因此,您永远不想使用 $( ... ) 来填充 tarfiles.txt,因为这是将命令的输出捕获到变量中的方式,而您要做的是将文件名存储在变量中。