Учитывая следующее расположение папки:
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" для каждого рекурсивного ответвления папки соответственно.
То, что работало на меня, было следующим сценарием удара:
#!/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 в конце). Я определил эту ошибку только после того, как ответы были уже предоставлены.
Вы сделали бы что-то вроде этого:
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"
.
Функция оболочки (не протестирована):
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 .
Ответ αғsнιη содержит правильное решение с find
, но если у Вас есть много каталогов, звоня один find
после того, как другой может быть довольно медленным. Если Вы хотите использовать все свои ядра процессора и работать find
процессы параллельно я рекомендую GNU parallel
для задачи:
parallel find {} -type f -regex "[^/]*/CMakeList.txt" -print -quit -o -regex "[^/]*/[^/]*/CMakeList.txt" -print ::: */