批处理文件根据文件名移动到目录结构

批处理文件根据文件名移动到目录结构

我正在编写一个脚本来根据文件名将文件移动到目录中。文件有yyyyddmm-xxxxxxx.jpg名称格式。所需的目录结构采用以下格式2013/01 Jan/31。我无法date正确格式化月份编号和月份名称之间的空格。当我尝试使用+%Y/%m %b格式时,收到以下错误消息:

日期:额外操作数`%b"'

我尝试过双引号和单引号,但没有成功。然而,date +"%Y/%m %b/%d"在以下情况下工作得很好sh

2013年10月27日

MOVEDIRSTR另外,是否有比使用和变量更好的方法来生成目录名称MOVEDIR(请参阅脚本)?

这是我当前的脚本:

FLIST=`ls "$IMGDIR" | grep -E '^.*\.jpg$'`

# If there are files to move
if [ -n "${FLIST}" ]; then
    # For each file
    while read -r line; do
        # Parse filename to YYYY/mm Mmm/Dd
        echo $line
        MOVEDIRSTR=`sed -r -e 's:([0-9]{4})([0-9]{2})([0-9]{2}).*:date -d \1-\2-\3 +%Y/%m_%b/%d:' <<< "$line"`
        MOVEDIR=`$MOVEDIRSTR`

        # If a directory does not exist, create it
        [ -d "$ARCHIVEDIR/$MOVEDIR" ] || (mkdir -p "$ARCHIVEDIR/$MOVEDIR")

        # Move file into YYYY/mm Mmm directory
        # mv -f "$IMGDIR/$line" "$ARCHIVEDIR/$MOVEDIR"
    done <<< "$FLIST"
fi

答案1

您必须在+符号后引用日期格式。

$ date +"%Y/%m %b"
2013/10 Oct

关于变量。$MOVEDIRSTR似乎没有必要。

MOVEDIR=$(sed -r -e 's:([0-9]{4})([0-9]{2})([0-9]{2}).*:date -d \1-\2-\3 +%Y/%m_%b/%d:' <<< "$line")

由于$FLIST您正在解析该目录中的日期,因此我没有看到更干净的方法。

更新#1

鉴于 OP 在下面的评论中的反馈,他正在使用 QNAP 设备,因此很可能拥有 BusyBox 提供的这些命令的淡化版本。如果您像这样查看 date 命令:ls -l /bin/date它可能是一个名为 busybox 或类似内容的可执行文件的链接。这些命令功能不全,因此会出现问题。

他证实了这一点:

你也许是对的。我的日期是它自己的可执行文件,但是 /bin/sed -> busybox

鉴于这些限制,上述方法可能不起作用,因为您使用这些工具使用的功能有限。

答案2

首先,我会使用一个 glob 来避免解析 ls.jpg并以这种迂回方式获取文件列表。其次,您可以使用 shell 本身(不需要sed)来提取日期部分:

shopt -s nullglob
for file in "$IMGDIR"/*.jpg; do
    file_name="$(basename file)"
    printf "%s\n" "$file_name"
    numbers="${file%-*}"
    year="${numbers%[0-9][0-9][0-9][0-9]}"
    monthday="${numbers#[0-9][0-9][0-9][0-9]}"
    month="${monthday%[0-9][0-9]}"
    day="${monthday#[0-9][0-9]}"
    movedir="$(date -d "$year-$month-$day" +"%Y/%m %b/)"
    movefile="$(date -d "$year-$month-$day" +"%Y/%m %b/%d)"
    [ -d "$ARCHIVEDIR/$movedir" ] || mkdir -p "$ARCHIVEDIR/$movedir"
    mv "$file" "$movefile"
done

当然,这假设您的date命令具有足够完整的功能集,因为您提到它是来自 BusyBox 的单独可执行文件。如果您的日期字符串长度不正好是 8 位数字,它也会中断。

答案3

看看以下是否可以解决日期提取和格式化部分:

$ f=20130131-abcdefgh.jpg
$ [[ $f =~ ^([[:digit:]]{4})([[:digit:]]{2})([[:digit:]]{2}) ]]
$ yyyy=${BASH_REMATCH[1]}
$ mm=${BASH_REMATCH[2]}
$ dd=${BASH_REMATCH[3]}
$ date -d ${yyyy}-${mm}-${dd} +'%Y/%m %b/%d'
2013/01 Jan/31

相关内容