当使用变量而不是硬编码文件名时调查 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
里面有内容.
您似乎希望 diff
将 tarfiles.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
,因为这是将命令的输出捕获到变量中的方式,而您要做的是将文件名存储在变量中。
我有一个脚本可以在指定目录中查找特定类型的文件,如果它们存在,则在创建 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
里面有内容.
您似乎希望 diff
将 tarfiles.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
,因为这是将命令的输出捕获到变量中的方式,而您要做的是将文件名存储在变量中。