如何返回具有相同目录名的文件列表?

时间:2017-01-19 21:59:48

标签: bash loops sorting find glob

我有以下目录结构:

├── 15_10_29
│   ├── NAME
│   ├── NAME_2
│   ├── NAME_3
│   ├── NAME_4
│   └── NAME_5
├── 15_11_09
│   ├── NAME
│   ├── NAME_2
│   ├── NAME_3
│   └── NAME_4
└── 15_11_17
    ├── NAME
    ├── NAME_2
    ├── NAME_3
    └── NAME_4

在每个NAME子目录中都有一个名为atom.pdb的文件。我想返回一个具有相同“NAME”目录名的atom.pdb文件列表。

./15_10_29/NAME/atom.pdb
./15_11_09/NAME/atom.pdb
./15_11_17/NAME/atom.pdb

./15_10_29/NAME_2/atom.pdb
./15_11_09/NAME_2/atom.pdb
./15_11_17/NAME_2/atom.pdb

......依此类推。

我似乎无法概念化如何做到这一点。我想我会想使用find但是我对bash globbing更好,在这种情况下代码必须很长,所以我确信有一个更优雅的解决方案。

修改:

find . -wholename '*atom.pdb' | sort -t / -k3,3正在返回所需的结果:

./15_10_29/NAME/atom.pdb
./15_11_09/NAME/atom.pdb
./15_11_17/NAME/atom.pdb
./15_10_29/NAME_2/atom.pdb
./15_11_09/NAME_2/atom.pdb
./15_11_17/NAME_2/atom.pdb
./15_10_29/NAME_3/atom.pdb
./15_11_09/NAME_3/atom.pdb
./15_11_17/NAME_3/atom.pdb
./15_10_29/NAME_4/atom.pdb
./15_11_09/NAME_4/atom.pdb
./15_11_17/NAME_4/atom.pdb
./15_10_29/NAME_5/atom.pdb

但是现在我不确定如何解析这些并通过“NAME”将它们分解为存储在数组或连接的字符串变量中。

编辑2: 以下是我提出的建议:

ARR=()
for i in /*/*/ ; do
    ARR+=($(basename ${i}))
done

while read i; do
    ARR2=(/*/${i}/atom.pdb)
    echo ${ARR2[@]}
done < <(echo ${ARR[@]} | tr " " "\n" | sort -u)

https://stackoverflow.com/a/41753869/5800081

3 个答案:

答案 0 :(得分:1)

您可以在Bash 4中执行此操作:

shopt -s globstar nullglob

# to find all files named atom.pdb
echo **/atom.pdb

# to find all atom.pdb files under a parent dir 'NAME'
echo **/NAME/atom.pdb

# to print all atom.pdb files, grouped by the same parent
while read -r dir; do
  files=$(echo **/"$dir"/atom.pdb)
  echo "Processing files $files"
  # do the processing
done < <(ls **/atom.pdb | cut -f2 -d/ | sort -u) # ls makes sure each file is on a different line, unless echo

给出这个输出:

Processing files 15_10_29/NAME/atom.pdb 15_11_09/NAME/atom.pdb 15_11_17/NAME/atom.pdb
Processing files 15_10_29/NAME_2/atom.pdb 15_11_09/NAME_2/atom.pdb 15_11_17/NAME_2/atom.pdb

答案 1 :(得分:1)

看起来像后期处理这种排序是一个很好的方法:

find . -wholename '*NAME*atom.pdb' | sort -t / -k3,3

如果你需要分组:

find . -name 'atom.pdb' | sort -t / -k3,3 | 
    awk -F/ '$3 != last{print ""}{last=$3}1'

答案 2 :(得分:0)

嗯,我毕竟以bash shell的方式成功解决了这个问题。

ARR=()
for i in /*/*/ ; do
    ARR+=($(basename ${i}))
done

while read i; do
    ARR2=(/*/${i}/atom.pdb)
    echo ${ARR2[@]}
done < <(echo ${ARR[@]} | tr " " "\n" | sort -u)

ARR包含一系列唯一的NAME值,ARR2包含在其父目录中具有相同NAME值的匹配文件名的全局列表。

如果有更优雅的方式来解决这个问题,请随时纠正我。它似乎有效。