【问题标题】:looping files with bash用 bash 循环文件
【发布时间】:2014-10-30 04:29:53
【问题描述】:

我不太擅长 shell 脚本,想问你一些关于文件大数据集循环的问题:在我的示例中,我在工作目录中有很多具有通用 .pdb 扩展名的文件。我需要循环所有这些,并且 i)打印每个循环文件​​的名称(w.o pdb 扩展名)并在此之后进行一些操作。例如,我需要使用每个文件的名称为工作目录之外的每个文件创建新目录,并将该文件复制到该目录。您可以在下面看到我的代码示例不起作用 - 它没有向我显示文件的名称,也没有为每个文件创建文件夹。请纠正它并告诉我我错在哪里

#!/bin/bash

# set the work dir 
receptors=./Receptors
for pdb in $receptors
do
  filename=$(basename "$pdb")
  echo "Processing of $filename file"
  cd ..
  mkdir ./docking_$filename
done

非常感谢您的帮助,

格莱布

【问题讨论】:

    标签: bash file loops


    【解决方案1】:

    要仅列出扩展名为 .pdb 的文件,请使用 $receptors/*.pdb

    所以不要只在 for 循环中给出路径,而是给出:

    for pdb in  $receptors/*.pdb
    

    删除扩展:

    将变量 ext 设置为要删除的扩展名,并使用 shell 扩展运算符“%”从文件名中删除扩展名,例如:

    ext=.pdb
    
    filename=${filename%${ext}}
    

    您可以在不更改当前目录的情况下创建新目录:

    所以要在当前目录之外创建一个目录,请使用以下命令

    mkdir ../docking_$文件名

    并使用 cp 命令将文件复制到新目录中

    修正后 您的脚本应如下所示:

    receptors=./Receptors
    ext=.pdb
    for pdb in $receptors/*.pdb
    do
      filename=$(basename "$pdb")
      filename=${filename%${ext}}
      echo "Processing of $filename file"
      mkdir ../docking_$filename
      cp $pdb ../docking_$filename
    
    done
    

    【讨论】:

      【解决方案2】:

      如果您的所有文件都包含在 .Repectors 文件夹中,您可以像这样循环每个文件:

      #!/bin/bash
      for pdb in ./Receptors/*.pdb ; do
          filename=$(basename "$pdb")
          filenamenoextention=${filename/.pdb/}
          mkdir "../docking_${filenamenoextention}"
      done
      

      顺便说一句:

      filenamenoextention=${filename/.pdb/}
      

      是否在变量$pdb 中进行搜索替换。语法为 ${myvariable/FOO/BAR},并将$myvariable 中的所有“FOO”子字符串替换为“BAR”。在您的情况下,它将“.pdb”替换为什么都没有,有效地将其删除。

      另外,更安全(如果$filename 包含多个".pdb"-子字符串)是删除最后四个字符,如下所示:filenamenoextention=${filename:0:-4}

      这里的语法是${myvariable:s:e},其中se 对应于开始和结束索引的数字(不包括在内)。它还允许您使用负数,即从末尾开始的偏移量。换句话说:${filename:0:-4} 说:从索引 0 开始从 $filename 中提取子字符串,直到到达倒数第四个字符。


      您的脚本遇到的一些问题:

      • for pdb in ./Receptors 仅循环 "./Receptors",而不是文件夹中的每个文件。

      • 当您更改到父目录 (cd ..) 时,您会为当前的 shell 会话执行此操作。这意味着您每次都继续访问父目录。相反,您可以在 mkdir 调用中指定父目录。例如mkdir ../thedir

      【讨论】:

      • 在这种情况下,$filenamenoextention 将包含 ./Receptors/filename - 这是不正确的。
      • :) 几乎...使用双引号 $(basename "$pdb") 因为文件名可以包含 <spaces> ;) - 同样,在 mkdir...
      • 非常感谢!顺便说一句,我不是 SHELL 脚本方面的专家。在 csh 而不是 bach 中编写相同的代码会有什么不同吗?对于完全不是程序员的人(比如我)来说,哪种语言会更好?
      • 不客气 :) 根据stackoverflow.com/questions/199661/…,最普遍接受的意见是坚持使用bash,除非你有充分的理由不这样做。似乎特别应该避免csh
      【解决方案3】:

      您正在遍历一个单项列表,我认为您想要获得的是 ./Receptors 的 content 列表:

      ...
      for pdb in $receptors/*
      ...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-13
        • 2019-08-26
        • 2012-09-06
        • 1970-01-01
        • 2012-02-26
        • 1970-01-01
        • 2012-03-27
        • 2021-01-25
        相关资源
        最近更新 更多