这是这个论坛的新手,但对于 RHEL 或脚本来说并不陌生。然而,这个有点让我烦恼。我有以下文件:
2019-05-01-00.34.00.msg
2019-05-02-00.36.00.msg
2019-06-14-01.38.00.msg
我想将它们存储在这样的目录中:
/2019/05/01/<Filename>
/2019/05/02/<Filename>
/2019/06/14/<Filename>
我想在将它们放入目录时也保留当前文件名。另外,我想用 bash 来做到这一点。
有什么想法吗?
答案1
您可以循环遍历名称,拆分名称-
,然后mkdir -p
创建目录(如果不存在),最后移动。像这样的东西:
for file in *msg; do
IFS="-" read -r year month day rest <<< "$file"
dir="$year/$month/$day/"
mkdir -p -- "$dir"
mv -- "$file" "$dir"
done
答案2
使用 perl 重命名工具这相当容易(不是util-linux 包中的重命名工具)。例如
设置:
$ touch 2019-05-01-00.34.00.msg 2019-05-02-00.36.00.msg 2019-06-14-01.38.00.msg
$ ls -l
total 2
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-05-01-00.34.00.msg
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-05-02-00.36.00.msg
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-06-14-01.38.00.msg
改名:
rename -n '
use File::Path qw(make_path);
if (-f $_ && m/^\d{4}-\d{2}-\d{2}-/) {
my ($y,$m,$d,$f) = split /-/,$_,4;
make_path("$y/$m/$d");
$_ = "$y/$m/$d/$f";
}' *.msg
该脚本首先忽略非常规文件 ( -f
) 或与模式不匹配的文件名^YYYY-MM-DD-
。如果给出垃圾输入,这可以防止它创建不需要的目录。
它将文件名分成四个元素。前 3 个是嵌入在文件名中的年、月和日($y
、$m
和$d
),第四个是文件名的其余部分($f
)。
它使用make_path()
来自的函数文件路径YYYY/
标准模块,用于递归地创建,YYYY/MM/
和的目录YYYY/MM/DD/
(类似于命令-p
的选项mkdir
)。我本来可以运行 perlmkdir()
函数三次,但我更喜欢使用File::Path
.
$_
然后它通过设置等于将文件重命名(即移动)到正确的目录中"$y/$m/$d/$f"
这是 perl 工作原理的关键rename
。您可以使用任何perl 代码,从简单的s/foo/bar/
搜索和替换样式到比这个答案中的脚本复杂得多的脚本。如果代码发生变化$_
,那么文件就会被重命名。如果$_
未更改,则不会重命名。
注意:这一行使用rename
's-n
选项,所以 a试运行仅有的。要使其真正重命名文件,请删除-n
或将其更改-v
为详细输出,如下所示:
2019-05-01-00.34.00.msg renamed as 2019/05/01/00.34.00.msg
2019-05-02-00.36.00.msg renamed as 2019/05/02/00.36.00.msg
2019-06-14-01.38.00.msg renamed as 2019/06/14/01.38.00.msg
顺便说一句,文件名可以提供给命令行(如上所示)或通过管道输入到脚本(rename
有一个-0
选项,因此它可以接受来自例如find ... -print0
或任何其他可以输出 NUL 分隔列表的输入文件名)。
最后,rename
将不是-f
覆盖现有文件,除非您使用aka选项告诉它--force
。