当使用变量而不是硬编码文件名时,调查bash脚本中的差异错误
我有一个脚本,它在指定的目录中查找特定类型的文件,如果它们存在,则在创建tar.gz之前生成一个具有基本名称的文件。压缩后,我通过运行diff检查来确保tarball包含所有文件 我创建了一对变量,它们是预压缩文件列表和tarball中的变量。当我运行包含变量的diff的if语句时,我收到以下错误:当使用变量而不是硬编码文件名时,调查bash脚本中的差异错误,bash,macos,echo,diff,Bash,Macos,Echo,Diff,我有一个脚本,它在指定的目录中查找特定类型的文件,如果它们存在,则在创建tar.gz之前生成一个具有基本名称的文件。压缩后,我通过运行diff检查来确保tarball包含所有文件 我创建了一对变量,它们是预压缩文件列表和tarball中的变量。当我运行包含变量的diff的if语句时,我收到以下错误: diff: missing operand after `/my/original/dir/filelist.txt' diff: Try `diff --help' for more inform
diff: missing operand after `/my/original/dir/filelist.txt'
diff: Try `diff --help' for more information.
我通过引用文件本身而不是创建的变量来解决这个问题。如果我在一个单独的bash脚本中运行If语句,那么使用变量就可以很好地工作,因此我完全不知道在我的较大脚本中我的错误是什么。下面,我将提供来自大型脚本的代码片段和diff语句作为自己的脚本,以供参考
if diff在其自己的脚本中:
#!/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)
是否执行以下步骤
- 从
变量引用的目录中名为$ARCHIVES
的压缩(tarredfiles.tar.gz
)tar文件(-z
)中提取文件名(-f
)列表-t
- 将(管道)文件名列表发送到
中,您可以在其中打印文件名的最后一个组成部分,即每行被awk
(/
)拆分时的最后一个字段(-F/
)$NF
- 将所有输出发送(重定向)到日志文件
$LOGS/tarfiles.txt
- 捕获任何其他输出(其中将没有输出!),并将其存储在
变量中TARFILES
TARFILES
始终为空,但文件TARFILES.txt
中包含内容
似乎您希望diff
将tarfiles.txt
的内容与filelist.txt
的内容进行比较,但您试图以一种与之不兼容的方式使用变量
形式的表达:
TARFILES=$( command goes here )
捕获该命令的输出
及
将命令的输出发送到文件中,然后捕获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
在使用will shell脚本时,很常见的情况是运行命令,这些命令会生成进入文件等的输出。在脚本的逻辑中,有一件事需要真正弄清楚,即当您希望变量包含实际内容(即命令的输出)时,以及当您希望它们包含文件名时
在您的例子中,您希望在碰巧包含文件名列表的两个文件(“tarfiles”和“filelist”)上运行diff,这意味着还有一些需要跟踪的内容,但实际上您希望使用命令的输出填充“tarfiles”,然后运行diff,在其中传入两个文件名“tarfiles”和“filelist”。因此,您永远不想使用
$(…)
来填充tarfiles.txt
,因为这就是将命令输出捕获到变量中的方式,您要做的是在变量中存储文件名。谢谢您的关注。tarfiles.txt是使用“>”填充的,我可以通过在长脚本中生成第一个脚本后运行它来验证这一点。我也可以取消注释“如果diff filelist.txt tarfiles.txt>/dev/null;然后
就成功了。只有当我尝试使用$FILELIST时,diff才会失败,因为diff:missing operand after
/…/logs/FILELIST.txt'`我确实使用tee尝试了您的建议,但只有tarball中的第一个文件返回了:diff:extra operand
firstfile.txt'`我的问题是,您试图存储在变量中的是什么?很重要,但你没有回答。我不太清楚你在这里想要实现什么。我可以看到哪里出了问题——很明显,你正在采取的步骤不会产生工作结果——但如果不了解你正在尝试做什么,我就不能给你关于如何解决问题的建议。根据您的评论,我现在猜测您希望TARFILES
引用文件TARFILES.txt
。如果这是你想要的,那么我会更新我的答案。再次感谢$TARFILES返回存储在TARFILES.txt中的内容,TARFILES.txt是以前生成的tarball中的文件名列表(仅限),它与$FILELIST进行比较,后者引用FILELIST.txt,并且它包含应压缩到tarball中的文件的文件名。所以我有一个文件目录,我列出它们并写入一个文件。然后我对文件进行焦油处理,并尝试检查是否所有文件都已压缩。我在tarball中搜索,保存它,然后尝试运行diff。如果我明确引用了它可以工作的文件,或者在另一个脚本中运行diff。谢谢。你的解释很清楚,我现在理解我的错误,你的解决方案非常有效。我挂断了tarfiles.txt的内容,却没有意识到$tarfiles是空的。非常感谢您的详细回复。在您的脚本之外,您是否为此创建了小型测试目录?您是否完成了cat filelist.txt tarfiles.txt
并确认(假设文件集正确)这些列表的排序顺序相同,列表的格式相同,行上没有前导或尾随空格字符?最后,您查看了输出(从cmd行)
TARFILES=$LOGS/tarfiles.txt
tar -tzf "$ARCHIVES/tarredfiles.tar.gz" | awk -F/ '{ if($NF != "") print $NF }' > $TARFILES