与我当前使用“cut”和“rev”的方法相比,从文件名中提取年份并将其移动到基于年份的目录的更快方法是什么?

与我当前使用“cut”和“rev”的方法相比,从文件名中提取年份并将其移动到基于年份的目录的更快方法是什么?

我有一个 Web 应用程序,它访问运行 Linux 的远程存储以获取一些文件,问题是远程存储当前有 300 万个文件,因此正常访问方式有点棘手。

因此,我需要编写一个脚本,使其更易于使用,该脚本将根据文件的创建日期,特别是它们的名称,将文件重新组织到多个文件夹中,我制作了该脚本并且它有效还好,本来打算做它该做的事,但是太慢了,十二个小时都完成不了(12:13:48 to be precise)

我认为缓慢是由于我拨打的多次电话cut造成的。rev


例子

ls我使用 for 循环的命令获取文件名,对于每个文件,我获取父目录,并且根据父目录,我可以获得正确的年份:

 case "$parent" in
                ( "Type1" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 2 | rev );;

                ( "Type2" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 2 | rev);;

                ( "Type3" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 1 | rev | cut -c 1-4);;

                ( "Type4" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 1 | rev | cut -c 1-4);;

                ( "Type5" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 1 | rev | cut -c 1-4);;
                esac

为了类型1文件数量:

the file==>MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf

我需要获取年份,以便执行反向剪切:

year=$(echo "$file" | rev | cut -d '_' -f 2 | rev );;

为了类型2文件数量:

the file==>MY_AMAZING_FILE_THAT_IMADE_IN_YEAR_WITH_TY.pdf 

ETC...

然后我可以mv自由地使用该文件:mv $file /some/path/destination/$year/$parent

但这是最简单的示例,有些文件要复杂得多,因此要获取 1 条信息,我需要执行 4 次操作,1 echo , 2rev and 1echo.

当脚本运行时,我的速度为,我通过执行脚本50 files/sec to 100 files\s获得了此信息。wc-l output.txt


我能做些什么来让它更快吗?或者用另一种方法来剪切文件名?我知道我可以使用sedawk或字符串操作,但我真的不明白如何使用。

答案1

要在不使用外部实用程序的情况下获取YEAR文件名的部分:MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf

name='MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf'

year=${name%_*}    # remove everything after the last '_'
year=${year##*_}   # remove everything up to the last (remaining) '_'

更新问题后:

将 PDF 文件从下面移动topdir到一个目录/some/path/destination/<year>/<parent>,其中<year>文件的文件名中包含年份,并且<parent>是文件所在原始目录的基本名称:

find topdir -type f -name '*.pdf' -exec bash ./movefiles.sh {} +

movefiles.sh是当前目录下的shell脚本:

#!/bin/bash

destdir='/some/path/destination'

for name; do
    # get basename of directory
    parent=${name%/*}
    parent=${parent##*/}

    # get the year from the filename:
    #  - Pattern:  _YYYY_         (in the middle somewhere)
    #  - Pattern:  _YYYYMMDD.pdf  (at end)
    if [[ "$name" =~ _([0-9]{4})_ ]] ||
       [[ "$name" =~ _([0-9]{4})[0-9]{4}\.pdf$ ]]; then
        year="${BASH_REMATCH[1]}"
    else
        printf 'No year in filename "%s"\n' "$name" >&2
        continue
    fi

    # make destination directory if needed
    # (remove echo when you have tested this at least once)
    if [ ! -d "$destdir/$year/$parent" ]; then
        echo mkdir -p "$destdir/$year/$parent"
    fi

    # move file
    # (remove echo when you have tested this at least once)
    echo mv "$name" "$destdir/$year/$parent"
done

答案2

您可以申请sed提取方法价值:

year=$(sed -E 's/.*_([0-9]{4})_TY\.pdf/\1/' <<<"$file")

相关内容