使用 shell 脚本选择具有唯一文件名格式和最近创建日期的特定 pdf?

使用 shell 脚本选择具有唯一文件名格式和最近创建日期的特定 pdf?

我需要一些脚本方面的帮助。我当前正在尝试选择满足文件名特定要求的 PDF 文件,以便将其移动到其他位置。

我尝试选择的文件名格式具有单独的部分,如下例所示:

I_XXX_PACK_6788669_6_9358869.pdf

我想做的是仅选择文件名中最后一部分的文件(例如9358869)并忽略目录中的所有其他 pdf 文件。

可以用 Unix 工具(POSIX find、sed、grep 等)来完成吗?我现在的主要问题是尝试只获取文件名中由 6 个分隔部分组成的一个文件,并忽略所有其他文件。

  • 另外,是否可以只选择系统时间前 1 小时创建的文件?我已经在其他文件类型上使用 sed 来检查时间,但没有在 pdf 文件上使用。所以我不确定这是否可能

答案1

您有诸如 之类的文件I_XXX_PACK_6788669_6_9358869.pdf,并且您只需要那些_与六个分隔部分匹配的文件,其中最后一个部分是9358869.

这将匹配至少六个_以 分隔的部分(*是匹配零个或多个字符的通配符,包括_)以 结尾9358869.pdf

*_*_*_*_*_9358869.pdf

您可以使用 查找过去一小时内修改(但未创建)的文件find,但此扩展名不是 POSIX:

find /path/to/directory -type f -mmin -60

为了允许 POSIX,您需要使用-newer {file},并设置{file}为适当的年龄。 POSIX 不提供将文件的修改日期时间设置为过去一小时的可靠方法,但正如您标记的那样我们可以用它:

printf -v curr '%(%s)T'
past=$(printf '%(%Y%m%d%H%M)T\n' "$((curr - 60*60))")
touch -t "$past" /path/to/timestamp

find /path/to/directory -type f -newer /path/to/timestamp

最后,将两者合并:

touch -t "$(printf -v curr '%(%s)T'; printf '%(%Y%m%d%H%M)T\n' "$((curr - 60*60))")" /path/to/timestamp
find /path/to/directory -type f -newer /path/to/timestamp -name '*_*_*_*_*_9358869.pdf'

答案2

find . -name '[!_]*_*_*_*_*_*[!_].pdf' ! -name '*_*_*_*_*_*_*' ! -name '*__*'

.pdf将报告名称以 5 且仅 5 个_字符结尾且根名称的每个_- 分隔部分不为空的文件(任何类型) 。

对于某些find实现,名称无法在当前语言环境中解码为文本的文件也将被排除。

为了限制在最后一个小时内修改的内容,正如 Chris 所说,某些实现支持的-newermt '1 hour ago',-mmin 60-mtime -1m不是标准的,并且 POSIXfind除了 之外没有等效项-newer some-file-with-a-last-modification-time-one-hour-ago

以 POSIX 方式创建一个搜索参考时间的常用方法是:

TZ=XXX0 touch -t "$(TZ=XXX1 date +%Y%m%d%H%M.%S)" some-file-with-a-last-modification-time-one-hour-ago

在时区(我们命名的时区,但名称与此处无关)date中调用where ,我们将其定义为比 UTC 晚 1 小时,并将产生的时间戳解释为UTC 时间(在也称为时区,但比 UTC 晚 0 小时) UTC)因此最终创建了一个一小时前的文件。XXXtouchdateXXX

之后您可以执行以下操作:

find . -name '[!_]*_*_*_*_*_*[!_].pdf' \
       ! -name '*_*_*_*_*_*_*' \
       ! -name '*__*' \
       -newer some-file-with-a-last-modification-time-one-hour-ago

如果像你的标签表明,您不限于使用 POSIXsh语法,那么您可以使用zsh不需要任何外部实用程序即可完成所有操作的地方:

set -o extendedglob
print -rC1 -- **/([^_]##_)(#c5)_[^_]##.pdf(ND-.mh-1)

在哪里:

  • **/匹配任何级别的子目录(包括0)
  • [^_]匹配除以下字符之外的任何字符_
  • x##匹配一个或多个xes,与 相同x(#c1,)
  • x(#c5)正好匹配 5 个xes
  • N如果没有匹配项,ullglob 将扩展为空,而不是报告错误。
  • Dotglob 包含隐藏的
  • .mh-1常规文件,最后修改时间不到一小时前(或将来),并-在符号链接解析后完成该检查。
  • print -rC1 -- print其论据r在 aw 和1 Column 上。

如果您想将匹配限制为最后 3 部分必须是十进制整数的文件,您可以将其更改为:

set -o extendedglob
print -rC1 -- **/([^_]##_)(#c3)<->_<->_<->.pdf(ND-.mh-1)

其中<-><1-20>数字匹配运算符的形式,但这里没有边界,因此匹配任何十进制整数(您也可以编写一个或多个 ASCII 十进制数字的任何序列[0-9]##)。


¹ 您可以添加-type f仅考虑类型的文件常规的(与 fifo、设备、目录、管道相反......)但请注意,它还会排除常规文件的符号链接。要包含这些,您需要-xtype f,但这也是一个非标准(GNU)扩展。

相关内容