我在检查是否存在以相同字符串/模式结尾的文件时遇到问题。文件名可能如下
abs_123.unl
xyz_123.unl
目前我的代码如下,对于单个文件工作正常,但如果有多个文件具有相同的模式,则如果条件失败
if [ -s $AZWORK/*$PRCSID.unl ]
then
tar -cvzf $WORK/INET_$PRCSID.unl.gz $WORK/*$PRCSID.unl
fi
这里$PCSID代表文件中的最后三位数字
如何让这个 shell 脚本适用于多个文件?
答案1
我会将文件的“查找”和“调整大小”委托给find
:
find "$WORK" -maxdepth 1 -name "*$PRCSID.unl" -type f ! -size 0 -print0 | \
xargs -0 --no-run-if-empty tar -cvzf "$WORK/INET_$PRCSID.unl.gz"
这样您还可以过滤掉可能具有该"*_123.unl"
模式的任何子目录。
选项find
:
-maxdepth 1
防止递归到子目录-name "*$PRCSID.unl"
匹配文件名,确保它被引用以防止*
被 shell 扩展。-type f
仅限文件! -size 0
尺寸很重要!-print0
打印 NUL 分隔的名称,这里不是严格必要的,但如果文件名中包含换行符,则不会造成伤害
选项/参数xargs
:
-0
假设 stdin 以 NUL 分隔(而不是换行符分隔)--no-run-if-empty
如果标准输入上没有数据,则不运行(即 find 确实有输出)- 该行的其余部分是要运行的命令,附加来自 stdin 的数据作为参数
答案2
你可以简单地这样做:
tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID.unl"
答案3
要检查是否存在与模式匹配的文件,您可以执行类似的操作
如果 ["$(shopt -s nullglob; printf "%s" "$WORK"/*"$PRCSID".unl)" != ""] 然后 tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl 菲
(我假设您不打算在一个位置查找.unl
文件,然后从另一个位置归档文件。)
shopt -s nullglob
当文件名模式不匹配任何内容时,会导致文件名模式“扩展”为空,因此,如果工作目录中没有名称以 结尾的文件123.unl
,则字符串参数"$WORK"/*"$PRCSID".unl
将消失,不会留下printf
任何内容可打印。
笔记:
- 您可以带上声明
shopt -s nullglob
的外部if
,例如,shopt -s nullglob # 可能在脚本的其他地方 ⋮ if [ "$(printf "%s" "$WORK"/*"$PRCSID".unl)" != "" ] 然后 tar -cvzf“$WORK/INET_$PRCSID.unl.gz”“$WORK”/*“$PRCSID”.unl 菲
如果您愿意通过执行脚本来使该行为(不匹配模式的空扩展)生效。 - 你应该总是引用 shell 变量(例如,
"$WORK"
和"$PRCSID"
),除非你有充分的理由不这样做,并且你当然你知道你在做什么。您可以零碎地完成它们,仅引用变量,例如,"$WORK"/*"$PRCSID".unl 和 "$WORK"/INET_"$PRCSID".unl.gz
或者您可以引用包含变量的整个单词,例如,“$WORK/”*“$PRCSID.unl”和“$WORK/INET_$PCSID.unl.gz”
但请注意,您不能这样做"$WORK/*$PRCSID.unl"
,因为这会将 括*
在引号中,从而阻止它充当文件名扩展模式(即通配符或 glob)。 - 由于您的文件名模式以您可以控制的目录名开头 - 特别是如果它是完整路径(以 开头
/
),或者您至少可以保证它不首先-
) — 那么你可能可以安全地echo
使用printf "%s"
; IE,如果 [“$(shopt -s nullglob;回声"$WORK"/*"$PRCSID".unl)" != "" ] 然后 tar -cvzf“$WORK/INET_$PRCSID.unl.gz”“$WORK”/*“$PRCSID”.unl 菲
当然,您也可以从此处的声明shopt -s nullglob
中删除该内容。if
另一种方法
如果你需要要具有if
- then
- else
(或至少有if
- then
),例如,要写入状态/日志/错误消息,您可能应该使用上面的内容。但是,如果您唯一关心的是tar
仅当那里有文件时才执行命令,那么您可以省去if
-then
并执行
(shopt -s 故障全局;tar -cvzf“$WORK/INET_$PRCSID.unl.gz”“$WORK”/*“$PRCSID”.unl)
shopt -s failglob
意味着,如果尝试使用包含不匹配任何内容的文件名模式的参数来执行命令,
命令没有执行。上面精确地实现了您问题中的代码试图实现的效果:tar
如果工作目录中有名称以 结尾的文件则执行该命令123.unl
,如果没有则不执行。
同样,您可以将命令shopt -s failglob
与tar
命令分开,例如,
shopt -s 故障全局 # 可能在脚本的其他地方 ⋮ tar -cvzf“$WORK/INET_$PRCSID.unl.gz”“$WORK”/*“$PRCSID”.unl如果您愿意通过执行脚本来实现该行为(不执行具有不匹配模式的命令)。
答案4
find
命令可以为您找到所需的文件,然后对结果执行任何命令,如下所示:
find $WORK -name *.unl -exec tar -zcvf $WORK/INET_$PRCSID.unl.gz {} \;