【问题标题】:How to return list of files with same directory name?如何返回具有相同目录名称的文件列表?
【发布时间】:2017-06-04 18:48:42
【问题描述】:

我的目录结构如下:

├── 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

【问题讨论】:

  • 为什么不直接find . -name atom.pdb -print
  • 我需要按基本名称对输出进行分组,以便将其分批输入另一个程序。这是我在寻找匹配的基本名称的逻辑。使用 find 打印所有 pdb 文件并按日期目录而不是基本名称对它们进行排序。
  • 你的基本名字只是atom.pdb,对吧?
  • 基本名称为“NAME”、“NAME_2”等

标签: bash loops sorting find glob


【解决方案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'

【讨论】:

  • 命令的第一部分效果很好,我现在有一个按 NAME 目录排序的列表。但是 awk 命令只是返回与整个路径相同的列表,它似乎没有对文件进行分组。理想情况下,我想将一个连接的文件名字符串存储到基于 NAME 目录的单独变量中,以提供给另一个程序。
  • awk 只是为了在组之间插入空行。
【解决方案2】:

你可以在 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

【讨论】:

  • 抱歉,我正在尝试按“NAME”匹配目录,然后将它们作为文件组返回,以便它们可以一起处理。
  • 这里的问题是“NAME”是可变的。因此,在调用 ls 之前,我首先需要找到所有唯一的 NAME 级目录名称。
  • find . -name 'atom.pdb' | sort -t / -k3,3 返回我所追求的与目录无关的排序,但我似乎无法将文件路径结果按 NAME 分组以存储到单独的变量中。
  • 我刚刚更新了我的答案,以便它遍历所有目录。
【解决方案3】:

好吧,我还是成功地以 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 值。

如果有更优雅的处理方式,请随时纠正我。不过它似乎有效。

【讨论】:

    猜你喜欢
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 2014-07-17
    • 1970-01-01
    • 2012-06-25
    • 2022-10-17
    • 1970-01-01
    相关资源
    最近更新 更多