Найдите первое соответствие в каждом ответвлении папки соответственно

Учитывая следующее расположение папки:

Current_folder
└── FolderA
|   └── CMakeList.txt
|   └── FolderAA
|       └── CMakeList.txt
|
└── FolderB
|   └── FolderBA
|   |   └── CMakeList.txt
|   |   └── FolderBAA
|   |       └── CMakeList.txt
|   |
|   └── FolderBB
|       └── CMakeList.txt
|
└── FolderC
    └── CMakeList.txt
    └── FolderCA
        └── CMakeList.txt

Как я могу использовать find (или любой другой инструмент) для создания вывода, подобного:

Current_folder/FolderA/CMakeList.txt
Current_folder/FolderB/FolderBA/CMakeList.txt
Current_folder/FolderB/FolderBB/CMakeList.txt
Current_folder/FolderC/CMakeList.txt

Означание, что поиск останавливается после соответствия с литеральным "CMakeLists.txt" для каждого рекурсивного ответвления папки соответственно.

3
задан 8 March 2018 в 16:51

4 ответа

То, что работало на меня, было следующим сценарием удара:

#!/bin/bash
file_of_interest="CMakeList.txt"
latest_directory_wih_match=""

for current_directory in $(find -type d);
do
  if [[ (${latest_directory_wih_match} == "") || (! ${current_directory} == ${latest_directory_wih_match}*) ]];
  then
    if [ -f ${current_directory}/${file_of_interest} ]
    then
      latest_directory_wih_match=${current_directory}
      echo ${latest_directory_wih_match}/${file_of_interest}
    fi
  fi;
done

Ответ @dessert работал на минимальный пример выше также. Используя его на моей фактической структуре папок (~4000 папок) он все еще давал неправильные результаты. Я не уверен почему, чтобы быть честным.

Когда я попробовал решение @muru, оно не прекратит выполняться. Я предполагаю, что функция, называя себя не прерывается правильно? Не уверенный в причине здесь также.

PS: В фактическом Проекте CMake на самом деле называют файл, "CMakeLists.txt" (отметьте дополнительный s в конце). Я определил эту ошибку только после того, как ответы были уже предоставлены.

0
ответ дан 1 December 2019 в 16:18

Вы сделали бы что-то вроде этого:

for path in ./*;do find "$path" -type f -name "CMakeList.txt" -print -quit ;done
./FolderA/CMakeList.txt
./FolderB/FolderBB/CMakeList.txt
./FolderC/CMakeList.txt

Это распечатает путь файла и -quit как только первый файл с подобранным именем, найденным от каждого пути то питание к find "$path".

1
ответ дан 1 December 2019 в 16:18

Функция оболочки (не протестирована):

search () (
  if [ -f "$1"/CMakeList.txt ]
  then
    # if you get a file, print and stop recursing
    echo "${1%/}/CMakeList.txt"
    return
  fi
  for d in "$1"/*/
  do
    # nothing found in this directory, recurse to subdirectories
    search "${d%/}"
  done
)
search .
1
ответ дан 1 December 2019 в 16:18

Ответ αғsнιη содержит правильное решение с find, но если у Вас есть много каталогов, звоня один find после того, как другой может быть довольно медленным. Если Вы хотите использовать все свои ядра процессора и работать find процессы параллельно я рекомендую GNU parallel для задачи:

parallel find {} -type f -regex "[^/]*/CMakeList.txt" -print -quit -o -regex "[^/]*/[^/]*/CMakeList.txt" -print ::: */
1
ответ дан 1 December 2019 в 16:18

Другие вопросы по тегам:

Похожие вопросы: