我需要一些关于重命名目录的bash脚本的帮助:
我想先重命名六个目录才能进行分析:
这是重命名的原始目录名:
MCIA-1-control_20170509
MCIA-2-control_20170509
MCIA-03-timesport_20170717
MCIA-04-timesport_20170717
MCIA-05-timesport_20170717
MCIA-6-timesport_20170717
我需要重命名如下:
subj-1-control
subj-2-control
subj-3-timesport
subj-4-timesport
subj-5-timesport
subj-6-timesport
我已经声明了几个变量如下:
$fnIDs #e.g.MCIA-1-control_20170509...
$ren #e.g. 1-control...
$raw_dir #data directory
然后我运行这个循环,但结果并不像我期望的那样:
for fn in ${fnIDs}; do
echo "+++this is all folder name for rename: fnIDs:${fnIDs}+++"
echo "+++renameing folder: fn:${fn}+++"
for rn in ${ren}; do
echo "=======ADD "subj" to rename the subj folder==========="
refn=subj-"$rn" #e.g. subj-1-control...
echo "refn:$refn"
echo "rename folder $fn to $refn"
if ( test -d "$raw_dir"/"$fn"); then #if dir exist then
cp -R "$raw_dir"/"$fn" "$raw_dir"/"$refn" #copy and rename file
echo "cp rename the subj folder:$raw_dir/$refn"
elif ( test -d "$raw_dir"/"$refn");then
echo "++++++renamed subject folder already exists+++++++"
else
echo "+++++somthing went wrong!Name of subject folder does not exists check "$fn $refn"+++++++++"
exit
fi
done
done
当我执行上述脚本时,他们执行以下操作:
+++renameing folder: fn:MCIA-1-control_20170509+++
=======rename the subj folder===========
renfn:subj-1-control
rename folder MCIA-1-control_20170509 to subj-1-control
rename folder MCIA-1-control_20170509 to subj-2-control
我想做的是:
rename folder MCIA-1-control_20170509 to subj-1-control
rename folder MCIA-2-control_20170509 to subj-2-control...
基本上,它将原始文件夹名称重命名为六个不同的subj文件夹名称... 我被困在这里一段时间......
感谢您帮助我...
答案 0 :(得分:1)
这可以使用与捕获组匹配的bash正则表达式来完成。
read -r -d '' input <<END
MCIA-0-control_20170509
MCIA-1-control_20170509
MCIA-2-control_20170509
MCIA-03-timesport_20170717
MCIA-04-timesport_20170717
MCIA-05-timesport_20170717
MCIA-6-timesport_20170717
END
for name in $input; do
[[ $name =~ ^MCIA-0*([[:digit:]]+)-(control|timesport)_[[:digit:]]+$ ]] &&
echo mv "$name" "subj-${BASH_REMATCH[1]}-${BASH_REMATCH[2]}"
done
mv MCIA-0-control_20170509 subj-0-control
mv MCIA-1-control_20170509 subj-1-control
mv MCIA-2-control_20170509 subj-2-control
mv MCIA-03-timesport_20170717 subj-3-timesport
mv MCIA-04-timesport_20170717 subj-4-timesport
mv MCIA-05-timesport_20170717 subj-5-timesport
mv MCIA-6-timesport_20170717 subj-6-timesport
^
:匹配字符串的开头。MCIA-
:匹配当前目录前缀。0*
:可选择匹配任意数量的前导零。这些不会进入捕获组,因为我们想要丢弃它们。([[:digit:]]+)
:丢弃前导零后,将一个或多个剩余数字捕获到第一个捕获组中。-
:匹配并丢弃其他连字符。(control|timesport)
:捕获&#34;控制&#34;或&#34; timesport&#34;进入第二个捕获组。_[[:digit:]]+
:匹配所有其他内容。$
:匹配字符串结尾。如果输入字符串匹配,则构建mv
命令,并将目标作为&#34; subj&#34;,第一个捕获组和第二个捕获组的串联。出于测试目的,我的代码示例使用echo
来打印命令而不是运行它。您可以根据需要扩展验证,存在检查等,就像您在原始代码示例中所做的那样。
有关bash中正则表达式的更多详细信息,请参阅Advanced Bash-Scripting Guide - 18.1. A Brief Introduction to Regular Expression。
答案 1 :(得分:1)
解决问题的另一种方法是将-_
添加到IFS
并将每个目录分成四个组件,将subj-
添加到开头并使用$(())
来解析/从第二个组件中删除前导零,然后使用第三个未更改的,例如(例如,我只是从文件中读取您的dirnames,但您可以使用globbing或find
将它们提供给while循环),例如。
$ cat dirs.txt
MCIA-1-control_20170509
MCIA-2-control_20170509
MCIA-03-timesport_20170717
MCIA-04-timesport_20170717
MCIA-05-timesport_20170717
MCIA-6-timesport_20170717
然后它只是一个简单的:
$ oifs="$IFS"; IFS="$IFS-_"; ## save old IFS, set new IFS
while read -r dir; do ## read each dirname
arr=( $dir ) ## separate into array elements
echo "mv $dir subj-$((${arr[1]}))-${arr[2]}" ## use elements 1, 2
done < dirs.txt
IFS="$oifs" ## restore original IFS
mv MCIA-1-control_20170509 subj-1-control
mv MCIA-2-control_20170509 subj-2-control
mv MCIA-03-timesport_20170717 subj-3-timesport
mv MCIA-04-timesport_20170717 subj-4-timesport
mv MCIA-05-timesport_20170717 subj-5-timesport
mv MCIA-6-timesport_20170717 subj-6-timesport
为避免使用数组,您可以执行类似以下操作:
$ while read -r dir; do
echo $dir |
{ IFS="$IFS-_"; read -r a b c d; echo "mv $dir subj-$((b))-$c"; }
done < dirs.txt
mv MCIA-1-control_20170509 subj-1-control
mv MCIA-2-control_20170509 subj-2-control
mv MCIA-03-timesport_20170717 subj-3-timesport
mv MCIA-04-timesport_20170717 subj-4-timesport
mv MCIA-05-timesport_20170717 subj-5-timesport
mv MCIA-6-timesport_20170717 subj-6-timesport