我有一个文件夹,其中包含以下形式的文件的文件夹
resultstatsDF_iris_2017-05-26--21-33-35-437096_methodnr-2_percentage-0.05_seed-0.wcr
我想删除其中每个的日期和时间,所以在这种情况下得到
resultstatsDF_iris_methodnr-2_percentage-0.05_seed-0.wcr
我如何在 bash 中执行此操作?
答案1
如果你真的想做的话“用bash”, 然后
find . -name '*.wcr' -execdir bash -c '
shopt -s extglob; for f; do echo mv -- "$f" "${f/_+([0-9-])_/_}"; done
' bash {} +
+([0-9-])
这依赖于匹配集合中出现的一个或多个字符的扩展 glob[0-9-]
您可以使替换更加具体,例如,${f/_2017+([0-9-])_/_}
如果简单地匹配数字和破折号过于通用。
注意:删除 echo
一旦你确定它正在做你想做的事。
答案2
使用find
+prename
(Perl 重命名)命令:
find yourfolder -type f -name "*.wcr" -exec prename 's/^(.+)_[0-9]{4}-[0-9]{2}-[0-9]{2}[^_]+(_.*)$/$1$2/' {} +
要查看prename
结果而不执行操作,请添加-n
选项 (打印要重命名的文件的名称,但不重命名):
man rename
[0-9]{4}-[0-9]{2}-[0-9]{2}
- 模式指向日期-like 子串(例如2017-05-26
)
答案3
使用Perl 重命名命令(任一变体,但不是 util-linux rename
):
find . -type f -name \*.wcr -exec rename 's/_\d{4}-(\d{2}-){2}-(\d{2}-){3}\d+_/_/' {} +
答案4
如果文件始终是一层目录深度,那么您可以使用类似for x in */*_20*_*
.使用哪种模式取决于可能存在您不想重命名的其他文件。我刚刚给出的模式假设日期以 开头20
,并且名称包含的所有文件_20
以及之后的另一个取消划线都应该重命名。
您可以使用 shell 循环进行重命名参数扩展构造来构建新的文件名。
for old_name in ./*/*_20_*_*; do
base=${old_name##*/} # remove the directory part
prefix=${base%%_20*} # remove everything from _20
suffix=${base#*_20} # remove everything up to _20
suffix=${suffix#*_} # ... then everything before the first remaining _
mv "$old_name" "${old_name%/*}/${prefix}_${suffix}"
done
如果文件的深度不同,在 bash ≥4.3 中,您可以运行shopt -s globstar
then for x in **/*_20*_*; …
。这图案**
globstar
如果打开,则匹配任何目录深度。这也适用于 bash 4.0–4.2,但需要注意的是它还会遍历目录的符号链接。这也适用于 zsh 和 ksh,无需任何警告,在 zsh 中开箱即用,set -o globstar
在 ksh 中也适用。