我想识别子目录中满足某些字符串条件的文件,然后使用目录名的最后部分重命名这些文件,向上 2 个目录(“pd1”?),然后我想将所有重命名的文件移动到单独的目录。
更详细:假设我从目录运行假设的代码/x/y/z
,并且该目录中的目录名称类似于“ 20150416_110508_3006
”。我要重命名的文件位于(示例)“ /x/y/z/20150416_110508_3006/dicom
”中,示例文件名“ o20150416_110508MPRAGESAGs002a1001.nii
”。与类似文件区分开来的文件名的重要元素是前缀“ o
”、s002a
中间的“”和扩展名“ .nii
”。
我想用 pd1 目录的最后部分重命名这些文件,在本例中为“ 3006
”,因此为“ 3006.nii
”。然后对所有适用的文件执行此操作后,我想将重命名的文件移动到“ /x/y/z
”中的目录。
答案1
和zsh
:
autoload zmv # best in ~/.zshrc
zmv -n '/x/y/z/*_*_(*)/dicom/o*s002a*.nii' '${f:h}/$1.nii'
或者:
zmv -n '/x/y/z/*_*_(*)/dicom/o*s002a*.nii' '/x/y/z/somedir/$1.nii'
将它们移至somedir
中/x/y/z
。
-n
当您对它执行您想要的操作感到满意后,删除它以实际进行重命名。
zmv
将在开始任何重命名之前检测冲突的重命名。对其他 shell 执行类似的操作bash
需要更长的脚本。就像是:
#! /bin/bash -
typeset -A seen
shopt -s nullglob
for file in /x/y/z/*_*_*/dicom/o*s002a*.nii; do
tag=${file%/*/*}
tag=${tag##*_}
if [[ ${seen[$tag]} ]]; then
printf >&2 '"%s" and "%s" both map to "%s"\n' "$file" "${seen[$tag]}" "$tag"
exit 1
fi
seen[$tag]=$file
done
for tag in "${!seen[@]}"; do
echo mv -i -- "${seen[$tag]}" "/x/y/z/somedir/$tag"
done
(未经测试)
(删除echo
来执行重命名)。
请注意,bash
关联数组(与 ksh93 或 zsh 相反)有一个错误/限制,即元素不能带有空键。因此,如果您有一些foo_bar_/dicom/*.nii
文件,则无法正常工作,因此即使对于这种编程方法,我仍然会使用zsh
orksh93
代替bash
.