从.txt文件中获取文件名,这些文件位于子目录中,并使用位于目录

时间:2018-03-02 03:18:45

标签: bash

我有一个包含60k子目录的目录。 每个子目录都有两个(子)子目录(2_4cov_bound)。我感兴趣的是子目录2_4。所以它看起来像这样:

main_directory/foo/2_4/

每个子目录foo包含一个.pdb文件 每个2_4子目录包含0个或更多.txt个文件。

所以它看起来像这样:

main_directory/foo/1A2C.pdb
main_directory/foo/2_4/XLS#A#207.txt
main_directory/foo/2_4/XLS#B#209.txt
main_directory/foo/2_4/XLS#C#207.txt
main_directory/foo/2_4/SOS#D#145.txt

我正在尝试将文件名中的第一个#之前的字母(本例中为XLSSOS)加入到pdb文件的文件名中:

1A2C_XLS_SOS.pdb

多个文件以XLS#开头,但每个前缀只能使用一次。

我遇到的第二个问题是,如果子目录2_4为空,则输出为1A2C_.pdb,我想摆脱它。因此,如果2_4为空,则不要处理它。只需在具有2_4个文件的.txt子目录上运行它。

我试图用bash写一些内容,但这仅适用于.txt中的一个2_4文件,并且还考虑了空2_4

所有这些带有新文件名的pdb文件都应该复制到另一个目录中。

我在bash中试过这个:

mkdir pdb_files
for i in */ ; do cd $i ; pwd ; a=`head -n1 2_4/*txt | awk '{print $4}' ` ; j=`ls *pdb` ;  cp $j ../pdb_files/${j//.pdb/_$a}.pdb ; cd ../ ; done

我是从main_directory运行它。

1 个答案:

答案 0 :(得分:1)

这里有一个裂缝:

TARGETDIR=./pdb_files
for dir in $(find . -maxdepth 1 -type d -not -name .)
do
  PREFIXES=( $(
    for file in ${dir}/2_4/*.txt
    do
      filename=$(basename $file)
      echo ${filename%%\#*.txt}
    done | sort -u 
  ) )

  if [ ${PREFIXES[0]} != '*.txt' ]
  then
    for oldpdb in ${dir}/*.pdb
    do
      pdbname=${oldpdb%%.pdb}
      pdbsuffix=$(IFS=_ ; echo "${PREFIXES[*]}")
      newpdb=${TARGET}/$(basename $pdbname)_${pdbsuffix}.pdb
      echo -------------------------
      echo Directory: $dir
      echo Old file name: $oldpdb
      echo New file name: $newpdb
      # I think this is what you want?
      cp $oldpdb $newpdb
    done
  else
    for oldpdb in ${dir}/*.pdb
    do
      echo -------------------------
      echo Directory: $dir
      echo Old file name: $oldpdb
      echo New file name: do not rename file
      # maybe you want to copy unmodified files?
      # cp $oldpdb $TARGET
    done
  fi
done

这是我的目录结构,来自main_directory:

main_directory/
├── foo
│   ├── 1A2C.pdb
│   └── 2_4
│       ├── SOS#D#145.txt
│       ├── XLS#A#207.txt
│       ├── XLS#B#209.txt
│       └── XLS#C#207.txt
├── foo2
│   ├── 1A2B.pdb
│   └── 2_4
└── run

并且' ./ run'的输出在main_directory中:

-------------------------
Directory: ./foo2
Old file name:
New file name: do not rename file
-------------------------
Directory: ./foo
Old file name: ./foo/1A2C.pdb
New file name: ./foo/1A2C_SOS_XLS.pdb

编辑:我错过了#34;将这些新文件复制到其他目录"有点,所以我稍微调整了一下脚本。

编辑2:对melpomene的称赞;很抱歉偷了你的问题,到我到这儿的时候你已经把它清理干净得足以让它变得有意义了。对不起:(

编辑3:嗯,目前还不是很清楚你想要对这些文件做些什么。困难的部分似乎打赌获得正确的新文件名,我认为这段代码就是这样。我已经改变它,所以它只打印出旧的和新的PDB文件名,从那里你可以插入你自己的逻辑来重命名或复制它们你认为合适吗?这个脚本不会cd进入每个目录,它会从主目录中执行所有操作。请尝试使用您的数据子集,并告诉我它是如何进行的。

编辑4:更改了我们移动新文件的逻辑

编辑5:在这里提出一些有问题的代码。这里的代码没有全部调试/尝试来演示脚本的内部工作原理。这将完成您所追求的目标,而不是谈论它一直在做什么。

编辑6:我之前的代码对于只有一个.txt文件的目录不起作用。这适用于我所知道的所有用例。

#!/bin/bash

TARGETDIR=./pdb_files

for dir in $(find . -maxdepth 1 -type d -not -name .)
do
  PREFIXES=( $(
    for file in ${dir}/2_4/*.txt
    do
      filename=$(basename $file)
      echo ${filename%%\#*.txt}
    done | sort -u
  ) )

  if [ ${#PREFIXES[@]} -ge 1 -a "${PREFIXES[0]}" != '*.txt' ]
  then
    for oldpdb in ${dir}/*.pdb
    do
      pdbname=${oldpdb%%.pdb}
      pdbsuffix=$(IFS=_ ; echo "${PREFIXES[*]}")
      newpdb=${TARGETDIR}/$(basename $pdbname)_${pdbsuffix}.pdb
      cp $oldpdb $newpdb
    done
  fi
done

之前的树:

main_directory
├── foo
│   ├── 1A2C.pdb
│   └── 2_4
│       ├── SOS#D#145.txt
│       ├── XLS#A#207.txt
│       ├── XLS#B#209.txt
│       └── XLS#C#207.txt
├── foo2
│   ├── 1A2B.pdb
│   └── 2_4
├── foo3
│   ├── 2_4
│   │   └── XLS#C#100.csv
│   └── 2A3B.pdb
├── foo4
│   ├── 2_4
│   │   └── XLS#D#201.txt
│   └── 3A3B.pdb
├── pdb_files
└── run

后:

main_directory
├── foo
│   ├── 1A2C.pdb
│   └── 2_4
│       ├── SOS#D#145.txt
│       ├── XLS#A#207.txt
│       ├── XLS#B#209.txt
│       └── XLS#C#207.txt
├── foo2
│   ├── 1A2B.pdb
│   └── 2_4
├── foo3
│   ├── 2_4
│   │   └── XLS#C#100.csv
│   └── 2A3B.pdb
├── foo4
│   ├── 2_4
│   │   └── XLS#D#201.txt
│   └── 3A3B.pdb
├── pdb_files
│   ├── 1A2C_SOS_XLS.pdb
│   └── 3A3B_XLS.pdb
└── run