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

Учитывая следующий макет папки:

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 в 17:51

8 ответов

, что работал для меня было следующие bash-скрипт:

[Ф1]

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

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

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

0
ответ дан 8 June 2018 в 15:37

Для меня работал следующий скрипт bash:

#!/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
ответ дан 17 July 2018 в 19:21

Для меня работал следующий скрипт bash:

#!/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
ответ дан 23 July 2018 в 20:05

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

[Ф1]

это выведет путь к файлу и [Ф2], как только первый файл с нашли подходящих имен из каждого путь, подавая в [Ф3].

1
ответ дан 8 June 2018 в 15:37
  • 1
    Ваше решение работало как прелесть для примера, который я представил изначально. Боюсь, я точно не сформулировал свой вопрос. Ибо я хотел бы также искать все дочерние элементы рекурсивно, а не только ветви верхнего уровня. В вашем текущем решении запись Current_folder/FolderB/FolderBB/CMakeLists.txt отсутствует. Я соответствующим образом обновил этот вопрос. То же самое верно для ответа @ десерт, кстати. – Tano 8 March 2018 в 13:40
  • 2
    @Тано, пожалуйста, попробовать ли [Ф1] соответствует критериям. – dessert 8 March 2018 в 14:07

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

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
ответ дан 8 June 2018 в 15:37
  • 1
    Наверное, лучше, чтобы полоску косую черту от [Ф1] и [Ф2]: [Ф3] – muru 8 March 2018 в 16:46

ответ αғsнιη содержит правильные решения с [Ф2], но если у вас много каталогов, позвонив по одному [Ф3] после другой может быть довольно медленным. Если вы хотите использовать все ядра процессора и запустить [F4] для процессов параллельно я рекомендую ГНУ [ф5] задачи:

[Ф1]
1
ответ дан 8 June 2018 в 15:37

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

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". [ ! d1]

1
ответ дан 17 July 2018 в 19:21

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

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". [ ! d1]

1
ответ дан 23 July 2018 в 20:05
  • 1
    Ваше решение работало как прелесть для примера, который я представил изначально. Боюсь, я точно не сформулировал свой вопрос. Ибо я хотел бы также искать все дочерние элементы рекурсивно, а не только ветви верхнего уровня. В вашем текущем решении запись Current_folder/FolderB/FolderBB/CMakeLists.txt отсутствует. Я соответствующим образом обновил этот вопрос. То же самое верно для ответа @ десерт, кстати. – Tano 8 March 2018 в 13:40
  • 2
    @Tano Попробуйте проверить соответствие for path in *; do find "$path" -type f -regex "[^/]*/CMakeList.txt" -print -quit -o -regex "[^/]*/[^/]*/CMakeList.txt" -print; done критериям. – dessert 8 March 2018 в 14:07

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

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