【问题标题】:Best way to tar and zip files meeting specific name criteria?满足特定名称标准的 tar 和 zip 文件的最佳方式?
【发布时间】:2018-05-10 18:35:21
【问题描述】:

我正在 Linux 机器上编写一个 shell 脚本,通过 crontab 运行,这意味着将所有早于当前日期的文件移动到一个新文件夹,然后 tar 并压缩整个文件夹。似乎是一项简单的任务,但由于某种原因,我遇到了各种障碍。我是新手并且是自学成才的,所以任何帮助或重定向将不胜感激。

归档文件的具体标准:

  • 所有日志文件都在/home/tech/logs/,所有pdf都在/home/tech/logs/pdf

  • 如文件名所示,所有文件都超过一天(文件名不包括$CURRENT_DATE

  • 所有文件必须为 *.log*.pdf(即,如果文件不是日志或 pdf 文件,则不要归档不包含 $CURRENT_DATE 的文件。

文件名格式细节:

所有的日志文件名都在home/tech/logs,格式为NAME 00_20180510.log,所有的pdf文件都在一个“pdf”子目录(home/tech/logs/pdf)中,格式为NAME 00_20180510_00000000.pdf(“20180510”将是任何时候该文件已创建,0 将是任意数字)。我需要使用名称而不是文件元数据作为创建日期,并且名称不包括当前日期的所有文件(pdf/log)都是“旧的”。我也不能只移动名称中不包含$CURRENT_DATE 的所有文件,因为它会包含任何非*.pdf*.log 文件。

现在脚本会为旧文件 (mkdir -p /home/tech/logs/$ARCHIVE_NAME/pdf) 创建一个带有新 pdf 子目录的新文件夹。然后我想将旧日志移动到$ARCHIVE_NAME,并将所有旧pdf从原始pdf子目录移动到$ARCHIVE_NAME/pdf

当前代码:

find /home/tech/logs -maxdepth 1 -name ( "*[^$CURRENT_DATE].log" "*.log" ) -exec mv -t "$ARCHIVE_NAME" '{}' ';'

find /home/tech/logs/pdf -maxdepth 1 -name ( "*[^$CURRENT_DATE]*.pdf" "*.pdf" ) -exec mv -t "$ARCHIVE_NAME/pdf" '{}' ';'

这不起作用,因为它将$CURRENT_DATE 中的数字视为要排除的数字列表而不是文字字符串。

我考虑过像这样使用 tar 的排除选项:

tar -cvzPf "$ARCHIVE_NAME.tgz" --directory /home/tech/logs --exclude="$CURRENT_DATE" --no-unquote --recursion --remove-files --files-from="/home/tech/logs/"

但是 a) 它不起作用,并且 b) 从理论上讲,它会包含所有不是 *.pdf*.log 文件的文件,这将是一个问题。

我是否过于复杂了?有没有更好的方法来解决这个问题?

【问题讨论】:

标签: linux bash shell zip tar


【解决方案1】:

我会使用 bash 的扩展 glob 功能来解决这个问题,它允许您否定模式:

#!/bin/bash

shopt -s extglob

mv /home/tech/logs/*!("$CURRENT_DATE")*.log "$ARCHIVE_NAME"
mv /home/tech/logs/pdf/*!("$CURRENT_DATE")*.pdf "$ARCHIVE_NAME"/pdf

启用extglob 后,!(pattern) 会扩展到与模式(或管道分隔模式列表)不匹配的所有内容。

使用find 应该也可以:

find /home/tech/logs -name '*.log' -not -name "*$CURRENT_DATE*" -exec mv -t "$ARCHIVE_NAME" {} +

【讨论】:

    【解决方案2】:

    基于@tom-fenech 答案,优化以避免许多mv 调用:

    find /home/tech/logs -maxdepth 1 -name '*.log' -not -name "*_${CURRENT_DATE?}.log" | \
      xargs mv -t "${ARCHIVE_NAME?}"
    

    通过管道处理文件的一个有趣功能是能够使用额外的工具(又名 grep :) 过滤它们,这可以(可以说)变得更具可读性,即 ->

    find /home/tech/logs -maxdepth 1 -name '*.log' | fgrep -v "_${CURRENT_DATE?}" | \
      xargs mv -t "${ARCHIVE_NAME?}"
    

    然后对于pdf 类似,顺便说一句,您可以通过将mv 替换为echo mv“试运行”

    --jjo

    【讨论】:

    • -exec {} + 根据生成的命令行的长度尽可能少地调用命令,类似于xargs。不同之处在于您的命令会在包含换行符的文件名的病态情况下中断,而我的则不会。
    猜你喜欢
    • 2013-02-05
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多