我正在处理数千个文件,其名称包含从 2001-01-01 到 2020-12-31 的连续日期。
此类文件的示例如下:
gpm_original_20010101.nc
gpm_cressman_20010101_cor_method-add_fac-0.5_pass-1_radius-500km.nc
gpm_cressman_20010101_cor_method-add_fac-0.5_pass-2_radius-250km.nc
gpm_cressman_20010101_cor_method-add_fac-0.5_pass-3_radius-150km.nc
gpm_cressman_20010101_cor_method-add_fac-0.5_pass-4_radius-75km.nc
gpm_cressman_20010101_cor_method-add_fac-0.5_pass-5_radius-30km.nc
.
.
.
gpm_original_20010131.nc
gpm_cressman_20010131_cor_method-add_fac-0.5_pass-1_radius-500km.nc
gpm_cressman_20010131_cor_method-add_fac-0.5_pass-2_radius-250km.nc
gpm_cressman_20010131_cor_method-add_fac-0.5_pass-3_radius-150km.nc
gpm_cressman_20010131_cor_method-add_fac-0.5_pass-4_radius-75km.nc
gpm_cressman_20010131_cor_method-add_fac-0.5_pass-5_radius-30km.nc
依此类推,直到2020-12-31
。我需要做的就是根据年份和月份将这些文件重新组织到新的文件夹中。
目录树需要遵循year
子目录的逻辑months
,如下所示:
2001
01
02
03
04
05
06
07
08
09
10
11
12
2002
01
02
03
04
05
06
07
08
09
10
11
12
等等。并且应根据文件名中的等效日期将文件移动到这些目录。例如:200101xx
名称中包含的所有文件都应移动到该2001/01
文件夹中。
使用 bash 实现此目的最直接的方法是什么?
答案1
如果我理解正确的话,这是我的建议:
for i in *.nc; do
[[ "$i" =~ _([0-9]{8})[_.] ]] && d="${BASH_REMATCH[1]}"
mkdir -p "${d:0:4}/${d:4:2}"
mv "$i" "${d:0:4}/${d:4:2}"
done
答案2
循环年份和月份:
#!/bin/bash
for year in {2001..2020} ; do
mkdir $year
for month in {01..12} ; do
mkdir $year/$month
mv gpm_cressman_${year}${month}* $year/$month
done
done
如果您每年和每月有太多长名称的文件(您声称“数千”),bash
可能会达到其限制(“参数列表太长”)。任何一个暂时增加 ulimit或使用xargs
:
#!/bin/bash
for year in {2001..2020} ; do
mkdir $year
for month in {01..12} ; do
mkdir $year/$month
find -maxdepth 1 -type f -name "gpm_cressman_${year}${month}*" |
xargs -I '{}' mv '{}' $year/$month
done
done
答案3
假设日期始终位于文件名中的相同位置,请将其放入脚本中:
#!/bin/bash
#
while $# -gt 0 ; do
file="$1"
shift
year="$( echo "$file" | cut -c 14-17)"
mnth="$( echo "$file" | cut -c 18-19)"
[[ -d $year/$mnth ]] || mkdir -p $year/$mnth
echo mv "$file" $year/$mnth
done
并使用以下命令调用脚本:
find . -maxdepth 1 -type f -name '*201*' -printf | \
xargs -r the_script
读man bash find xargs mkdir mv
。
echo
当您真正想要这样做时,请删除。