我是 ubuntu 和编程世界的新手,我真的不知道该怎么做!
我有一个文件夹,其中有很多文件,名称如下:
000_S_001_mpc_asd.json
000_S_001_mpc_asd.nii
000_S_001_mpc_asd_aa.nii
011_S_001_mpc_asd.json
011_S_001_mpc_asd.nii
011_S_001_mpc_asd_aa.nii
000_S_002_mpc_asd.json
000_S_002_mpc_asd.nii
000_S_002_mpc_asd_aa.nii
000_S_001_dtd_rty.bval
000_S_001_dtd_rty.bvec
000_S_001_dtd_rty.nii
000_S_001_dtd_rty.json
011_S_001_dtd_rty.bval
011_S_001_dtd_rty.bvec
011_S_001_dtd_rty.nii
011_S_001_dtd_rty.json
000_S_002_dtd_rty.bval
000_S_002_dtd_rty.bvec
000_S_002_dtd_rty.nii
000_S_002_dtd_rty.json
011_S_001_flf_lkj.json
011_S_001_flf_lkj.nii
011_S_001_flf_lkj_aa.nii
000_S_001_flf_lkj.json
000_S_001_flf_lkj.nii
000_S_001_flf_lkj_aa.nii
000_S_002_flf_lkj.nii
000_S_002_flf_lkj_aa.nii
假设 xxx_S_xxx 是主要名称,而文件名称的其余部分提供次要信息(我们称之为次要名称)。
我想在辅助名称中找到一个特定的名称,并以此名称创建一个文件夹(例如 mpc、dtd 或 flf),然后创建以每个文件的主要名称命名的子文件夹,并将相应的文件放入这些文件夹中。也许一张图片可以更好地解释我想说的话。
例如,上面我给出的名称的输出将如下所示:
期望输出:
可以从终端执行此操作吗?我将非常感激您的帮助。
我的操作系统是 Ubuntu 20.04 LTS
答案1
如果目标目录结构不存在,你可以砍掉小路分成几部分并按照所需的顺序排列。
#!/bin/bash
while IFS=_ read -r a b c d e; do
mkdir -p target/$d/${a##*/}_${b}_${c}; mv -t $_ ${a}_${b}_${c}_${d}_$e
done < <(printf %s\\n files/*)
或者正则表达式,其中数组BASH_REMATCH
记录匹配到的部件。第一个数组成员包含与整个正则表达式匹配的部分。括号中的子表达式匹配的子字符串将分配给以下成员。
#!/bin/bash
for i in files/*; do
if [[ $i =~ ^files/([0-9]+_S_[0-9]+)_(mpc|dtd|flf) ]]; then
mkdir -p target/${BASH_REMATCH[2]}/${BASH_REMATCH[1]}; mv -t $_ $i
fi
done
您还可以将该过程分为两个步骤,首先创建目录结构,然后awk
结合xargs
优化使用,例如重命名。mkdir
mmv
#!/bin/bash
builtin cd files
printf %s\\0 * | \
awk -F _ ' \
BEGIN{ RS = ORS = "\0" } { printf("../target/%s/%s_%s_%s\0", $4, $1, $2, $3) } \
' | xargs -0 mkdir -p
# Remember we have change our working directory.
mmv -m '*_S_*_*_*' '../target/#3/#1_S_#2/#1_S_#2_#3_#4'
答案2
我不太清楚如何纯粹在终端上做到这一点而不会变得太难阅读,但我认为你可以得到你想要的结果,或者至少可以开始这样做:
编辑:更新了评论中的信息。还交换了次要和主要,因为它们是倒置的。
编辑2:意识到虽然次要名称不再依赖于位置,但主要名称依赖于次要的位置。
#!/bin/bash
input_directory="/path/to/your/data"
output_directory="/path/to/your/output"
cd "$input_directory"
for file in *; do
if [ ! -f "$file" ]; then
continue;
fi
# place your secondary names inside "(mpc|flf|dtd)" seperated by '|'
secondary=$(echo "$file" | grep -o -E "(mpc|flf|dtd)");
princple=$(echo "$file" | grep -o -E "([0-9]+_S_[0-9]+)");
# skip over and alert that a secondary match was not found for a file
if [ "$secondary" == "" ]; then
echo "No secondary match found!! Skipping $file";
continue;
fi
destination="${output_directory}/$secondary/$princple"
# create the directories if they don't exist
if [ ! -d "$destination" ]; then
mkdir -p "$destination";
fi
# uncomment to move the files to the new directories if the test output
# from echo is correct
#mv "$file" "$destination"
# test to print result of moving the files
from=$(readlink -f "$file")
echo "$from -> $destination/$file"
done
grep -o -E "(mpc|flf|dtd)"
在文件名中搜索二级名称关键字之一,例如 (mpc、dtd 或 flf),然后将该词保存到二级变量中。
grep -o -E "([0-9]+_S_[0-9]+)
相同的想法,通过寻找 xxx_S_xxx 模式。
它可以按如下方式运行:bash script.sh
input_directory
和变量output_directory
需要填写正确的路径。此外,grep 语句中的字段“(mpc|flf|dtd)”可以填写其他辅助路径。