如何检查目录中是否存在多个文件并压缩相同的文件

如何检查目录中是否存在多个文件并压缩相同的文件

我在检查是否存在以相同字符串/模式结尾的文件时遇到问题。文件名可能如下

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 failglobtar命令分开,例如,

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 {} \;

相关内容