【问题标题】:Remove part of file name in multiple sub directories删除多个子目录中的部分文件名
【发布时间】:2020-02-15 10:04:10
【问题描述】:

主文件夹“Main”包含多个子文件夹(6900,159, 9997, ...),每个子文件夹包含 8 个项目(4 个文件(6900Log.final.out、6900Log.out、6900Log.progress.out、6900SJ .out.tab)、3 个文件夹(6900_STARgenome、6900_STARpass1、6900_STARtmp)和一个压缩文件(6900Aligned.sortedByCoord.out.bam))。 6900_STARtmp 包含更多子文件夹,但我不想更改 6900_STARtmp 中存在的子文件夹的名称。请看图

我想从 (6900Aligned.sortedByCoord.out.bam, 6900Log.final.out, 6900Log.out, 6900Log.progress.out, 6900SJ.out.tab) 中删除 6900 和从 (6900_STARgenome, 6900_STARpass1, 6900_STARtmp) 中删除 6900_

所以文件的名称应该是(Aligned.sortedByCoord.out.bam、Log.final.out、Log.out、Log.progress.out、SJ.out.tab、STARgenome、STARpass1、STARtmp)。

我尝试在 ubntu (18.04.3 LTS) 上运行以下脚本来重命名 SJ.out.tab 并计划对其余文件执行此操作,但它对我不起作用:

for filename in Main/*/*SJ.out.tab; do 
    #echo $filename
    describer=$(echo ${filename})        
    #mv "$filename" "${filename//${describer}/SJ.out.tab}"
done

我们将不胜感激。

【问题讨论】:

  • 请指明操作系统,如果是 Linux,请指明您使用的 shell。你的脚本尝试在 Linux 下看起来像 bash,但你仍然应该声明和标记操作系统。
  • 我可能只会使用for f in Main/*/* ; do mv "$f" $(echo "$f" | sed "s/^[0-9]*_*//") ; done。这也会将123___abc.out 更改为abc.out 之类的东西,我认为这是可以的。除非您使用扩展通配符功能,否则我认为您不能编写一个单一的通配符模式来表示文件名开头的任意数字字符串。
  • 我尝试在 Main/*/* 中使用 for f ;做 mv "$f" $(echo "$f" | sed "s/^[0-9]*_*//") ;完成但我收到文件错误 (6900Aligned.sortedByCoord.out.bam, 6900Log.final.out, 6900Log.out, 6900Log.progress.out, 6900SJ.out.tab) mv: 'star_output_first/6900/6900SJ.out .tab' 和 'star_output_first/6900/6900SJ.out.tab' 是同一个文件。文件 (6900_STARgenome, 6900_STARpass1, 6900_STARtmp) mv: cannot move 'star_output_first/6900/6900_STARgenome' to a subdirectory of its own, 'star_output_first/6900/6900_STARgenome/6900_STARgenome' m
  • 对不起,我忘了考虑路径:for f in Main/*/* ; do mv "$f" $(echo "$f" | sed "s/\/^[0-9]*_*/\//") ; done。另外,Main/*/*下有子文件夹吗?
  • 我试过这个,但仍然遇到同样的错误,是的,主文件夹中有大约 700 个子文件夹,此外,每个子文件夹包含 8 个文件。例如,对于存在于子文件夹中的文件 (6900Log.out),其路径类似于 Main/6900/6900Log.out,对于文件 (6900SJ.out.tab),其路径类似于 Main/6900/6900SJ.out.tab

标签: linux bash for-loop rename


【解决方案1】:

为确保您不会意外修改其他文件或目录,您应确保脚本将自身限制为仅文件与目录名称相同的数字或以数字开头的目录和一个下划线,并且只有一层深。

试试这个:

#!/bin/bash

declare    base_dir=/path/to/Main

cd ${base_dir}
while read subdir; do
  number=${subdir#./}
  for file in $(find ${subdir} -maxdepth 1 -type f -name "${number}*"); do
    mv ${file} ${subdir}/${file##./${number}/${number}}
  done
  for file in $(find ${subdir} -maxdepth 1 -type d -name "${number}_*"); do
    mv ${file} ${subdir}/${file##./${number}/${number}_}
  done
done < <(find . -maxdepth 1 -type d -regex './[0-9]*')

【讨论】:

  • 你错过了“!”在第一行中,是不是应该像 #!/bin/bash,其次我在“Main”文件夹中运行此脚本并遇到两个错误:./renaming_mapped_data: line 8: unexpected EOF while looking for matching ` `' 和这个错误 ./renaming_mapped_data: line 14: syntax error: unexpected end of file
  • 是的。我错过了'!在第一行(现已更正)。我怀疑您的本地脚本副本中存在剪切/粘贴错误。我的版本的第 8 行没有单引号。第 14 行的错误是第 8 行错误的副作用。
  • 我刚刚注意到第 6 行的另一个错字:sub_dir 应该是 subdir(现已更正)。
  • 我不知道为什么我会收到这种错误消息:mv:无法创建常规文件'/Aligned.sortedByCoord.out.bam':权限被拒绝 mv:无法创建常规文件'/ Log.final.out': 权限被拒绝
  • 非常抱歉。当我测试脚本时,我没有包含“mv”命令,因为我不想实际更改任何文件名。我只是仔细检查了上面的脚本,发现另一个不正确的变量名。在第 9 行和第 12 行,请将 ${dir} 更改为 ${subdir}。我现在已经在答案中更正了这一点。
猜你喜欢
  • 1970-01-01
  • 2021-04-14
  • 2012-08-23
  • 2022-11-17
  • 2019-02-10
  • 2017-01-01
  • 2016-04-29
  • 1970-01-01
  • 2016-11-11
相关资源
最近更新 更多