从文件名中提取年份以将它们移动到基于年份的目录比我目前使用 `cut` 和 `rev` 的方法更快的方法是什么?

Kin*_*ech 3 bash cut

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

所以我需要编写一个脚本,让它更容易使用,这个脚本将根据文件的创建日期和特别是它们的名称将文件重新组织到多个文件夹中,我制作了脚本并且它起作用了挺好的,本来打算做它想做的,但是太慢了,12个小时才能完全完成(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
Run Code Online (Sandbox Code Playgroud)

对于类型1的文件:

the file==>MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf
Run Code Online (Sandbox Code Playgroud)

我需要得到年份,所以我进行了反向切割:

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

对于类型 2的文件:

the file==>MY_AMAZING_FILE_THAT_IMADE_IN_YEAR_WITH_TY.pdf 
Run Code Online (Sandbox Code Playgroud)

等等...

然后我可以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 脚本获得了这个信息。


有什么我可以做的让它更快吗?或另一种剪切文件名的方法?我知道我可以使用sedorawk或 string 操作,但我并不真正理解如何。

Kus*_*nda 6

要在不使用外部实用程序的情况下获取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) '_'
Run Code Online (Sandbox Code Playgroud)

更新问题后:

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

find topdir -type f -name '*.pdf' -exec bash ./movefiles.sh {} +
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)