我需要通过读取文件名来移动文件。我必须移动系统生成的文件,并且名称包含时间戳。我需要通过按月读取文件名来移动文件。
如果文件名包含201601*.txt
,则移动到2016/January
目录。如果文件名包含201602*.txt
则移动到2016/February
目录等。
答案1
好吧,如果日期字符串位于文件名中并且所有文件都位于同一目录中,您可以执行以下操作:
mv 201601*.txt 2016/January
手动执行此操作 12 次会很痛苦,因此我将创建一个包含数字和相应月份名称的列表:
$ paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}')
01 January
02 February
03 March
04 April
05 May
06 June
07 July
08 August
09 September
10 October
11 November
12 December
然后解析它来构建mv
命令:
$ paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') |
while read num month; do echo mv "*2016$num*" 2016/"$month"; done
mv *201601* 2016/January
mv *201602* 2016/February
mv *201603* 2016/March
mv *201604* 2016/April
mv *201605* 2016/May
mv *201606* 2016/June
mv *201607* 2016/July
mv *201608* 2016/August
mv *201609* 2016/September
mv *201610* 2016/October
mv *201611* 2016/November
mv *201612* 2016/December
一旦您确定它满足您的需要,请删除echo
以实际移动文件:
paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') |
while read num month; do echo mv "*2016$num*" 2016/"$month"; done
解释
将使用 Perl 兼容正则表达式 ( )grep -Po '\s+\K[A-Z]\w{2,}')
运行,并且仅打印每行 ( ) 的匹配部分。使用的正则表达式将查找一个或多个空白字符 ( ),后跟一个大写字母 ( ) 和 2 个或多个单词字符 ( )。意思是“忽略在此之前的所有内容”,这将导致命令仅打印匹配字符串的部分grep
-P
-o
\s+
[A-Z]
\w{2,}
\K
后空白。整个过程只是打印月份列表。
答案2
兹什有一个很好的函数可以根据名称模式重命名文件:zmv
。在替换模式中,$f
指定整个原始名称$1
,$2
等是括号内的组。使用数组来存储月份名称。
autoload -U zmv
months=(January February March April May June July August September October November December)
zmv '(2016)(<1-12>)*.txt' '$1/$months[$2]/$f'
因为这里的模式很简单,所以使用循环将其适应 bash 和 ksh 并不是很痛苦。您需要注意一些事情:从月份数字中去掉前导 0,这样它就不会被解释为八进制;数组索引从 0 开始。
months=(January February March April May June July August September October November December)
for f in 2016[0-9][0-9]*; do
y=${f:0:4} m=${f:4:2}
mv -- "$f" "$y/${months[${m#0}]}/$f"
done
另一种方法是 Perl 重命名脚本(或者Debian版本或者Unicode::争斗版本)。
rename 'BEGIN {@months = qw(January February March April May June July August September October November December)}
s!^([0-9]{4})([0-9]{2})!$1/$months[$2]/&!' 2016[0-9][0-9]*
答案3
下面是一个bash
遍历文件的解决方案,移动那些与组件匹配的文件(对于2000-2099 范围内yyyymm
的值):yyyy
months=('' January February March April May June July August September October November December)
for f in 20[0-9][0-9][0-3][0-9]*
do
year=$(echo "$f" | grep -Po '^20\d\d') # Extract the four digit year, 20nn
mm=$(echo "$f" | grep -Po '^(?<=20\d\d)\d\d') # Find the two digit month number 01-12
month=${months[$mm]} # Convert to a month name
test -n "$year" -a -n "$month" && echo mv "$f" "$yyyy/$month/$f"
done
当您准备好运行时,请删除echo
前缀。mv
如果您知道所有文件都以以下开头,2016
则可以稍微简化处理:
for f in 2016[0-3][0-9]*
do
mm=$(echo "$f" | grep -Po '^(?<=2016)\d\d') # Find the two digit month number 01-12
month=${months[$mm]} # Convert to a month name
test -n "$month" && echo mv "$f" "2016/$month/$f"
done