根据文件名中的日期将文件排序到文件夹中?

根据文件名中的日期将文件排序到文件夹中?

已解决:请参阅评论中的更新。

我正在尝试根据该日期将文件名中带有日期的文件排序到文件夹中。这些文件的文件名中曾经有一个空格,如下所示。有一些旧文件,所以我也需要对它们进行排序。

调度传真_20180521121901.pdf

我们现在获取的文件名中没有空格,因此它只是 Dispatch_20180521124202.pdf

日期是 20180521,其余部分我认为是消息 ID,但我们不需要它。只是日期。

这次尝试使用 bash 脚本(ubuntu 18.04 盒子)最终创建了一个名为 2018-05-21 的文件夹,该文件夹位于文件所在目录的上一级目录,并将所有 pdf 文件放入该文件夹中。

    for x in /home/tb/temp/*.pdf
do
    d=$(date -r "$x" +%Y-%m-%d)
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

这最终以某种方式进入了一个名为“e”的文件夹。

for x in /home/tb/temp/*.pdf
do
    d="${x:4:4}-${x:8:2}-${x:10:2}"
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

这次尝试?我最终为每个 PDF 建立了一个文件夹。

/home/tb/20180521124202.pdf/Dispatch Fax_20180521124202.pdf /home/tb/20180521121901.pdf/Dispatch Fax_20180521121901.pdf

for x in /home/tb/temp/*.pdf
do
    d=$(echo "$x" | awk -F _ '{print $2}')
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

脚本来自之前的帖子这里这里这些对他们有用,但即使目标是相同的,我也没有同样的运气。

我的目标是最终从 rsync 填充临时目录(从另一台服务器提取这些文件),然后通过 cron,运行此脚本以根据日期将内容移动到文件夹中,并通过启用“选项+索引”的 Apache 提供该目录。这是一个仅限 Intranet 的页面,并且该特定计算机无法从外部访问。目录结构很简单。最终类似 /var/www/html/2018/5/21 等,遵循 YYYY/MM/DD 格式。

我只是不知道如何让它工作,而且我对 bash 脚本的了解非常生疏。我看过其他几个例子,比如这个但后来我发现它不适用于文件名中包含空格的文件。

我对想法持开放态度!

答案1

你的问题对我来说并不完全清楚,但我想我可能明白你想做什么。

这是您正在使用的循环:

for x in /home/tb/temp/*.pdf
do
    d="${x:4:4}-${x:8:2}-${x:10:2}"
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

您给出的示例文件名是:

  1. Dispatch Fax_20180521121901.pdf
  2. Dispatch_20180521124202.pdf

我突然想到的一个问题是你的参数替换表达式 ( d="${x:4:4}-${x:8:2}-${x:10:2}") 似乎没有产生正确的结果,例如:

> x='Dispatch Fax_20180521121901.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch- F-ax

> x='Dispatch_20180521124202.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch-_2-01

您可以尝试使用grep代替,例如:

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521

或者,如果您想添加连字符,您可以使用以下sed基于命令替换:

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
> echo ${d}
2018-05-21

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
> echo ${d}
2018-05-21

假设这是所需的结果(即您需要 形式的子目录%Y-%m-%d),我们可以将您的参数替换表达式替换为grep基于 - 的命令替换。这将为我们提供以下修改后的循环:

for filename in /home/tb/temp/*.pdf; do
    datestring=$(echo "${filename}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
    mkdir -p "${datestring}"
    mv -i -- "${filename}" "${datestring}/"
done

这应该会生成表单的子目录%Y-%m-%d并用适当的文件填充它们。


更新:根据您的评论,听起来您想要的是 form 的嵌套子目录%Y/%m/%d。为此,您需要分别提取年、月和日子字符串,例如:

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> year=${d:0:4}
> month=${d:4:2}
> day=${d:6:2}
> echo "${year}/${month}/${day}/"
2018/05/21/

这导致我们进入以下循环:

for filename in /home/tb/temp/*.pdf; do
    datestring=$(echo "${filename}" | grep -Po '\d{8}')
    year=${datestring:0:4}
    month=${datestring:4:2}
    day=${datestring:6:2}
    directory="${year}/${month}/${day}/"
    mkdir -p "${directory}"
    mv -i -- "${filename}" "${directory}"
done

答案2

如果您不必处理积极敌对的文件名,

sed -E 's/([0-9]{0,7}[^0-9]+)*([0-9]{8}).*/mkdir -p \2; mv "&" \2/e'
#         111111111111111111 2222222222 

该模式是 0 到 7 位数字,后跟一些非数字,任意次数,后跟 8 位数字,一次。第二个模式是 8 位数字,与日期匹配。

如果您没有 GNU sed,您可以代替标志e将结果通过管道传输到 shell 中。

相关内容