我正在编写一个脚本来根据文件名将文件移动到目录中。文件有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