We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[question][suggestion] Listing profile should be recursive
Hello,

I use multiple profiles, and those are organized in subdirectories:
   + `~/.conan/profiles/application/x64_gcc6_app1`
   + `~/.conan/profiles/application/x64_msvc_app1`
   + `~/.conan/profiles/compilers/x64_gcc6`
   + `~/.conan/profiles/compilers/x64_msvc`

The "applications" profile include other profiles etc. This works pretty well, so I assume 
using subdirectory in profiles is supported and is not a problem.

However, the `conan profile list` command does not list profiles contained in subdirectories.
I believe it should recursively search for profile files rather than only list the files available directly in the `~/.conan/profiles` directory.

I'm wondering if there is a particular reason why the search is limited to the `~/.conan/profiles` directory and if you'd be open to changing this behavior.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `conans/client/cmd/profile.py`
Content:
```
1 import os
2 
3 from conans.client.conf.detect import detect_defaults_settings
4 from conans.client.profile_loader import get_profile_path, read_profile
5 from conans.errors import ConanException
6 from conans.model.options import OptionsValues
7 from conans.model.profile import Profile
8 from conans.unicode import get_cwd
9 from conans.util.files import save
10 
11 
12 def _get_profile_keys(key):
13     # settings.compiler.version => settings, compiler.version
14     tmp = key.split(".")
15     first_key = tmp[0]
16     rest_key = ".".join(tmp[1:]) if len(tmp) > 1 else None
17     if first_key not in ("build_requires", "settings", "options", "env"):
18         raise ConanException("Invalid specified key: %s" % key)
19 
20     return first_key, rest_key
21 
22 
23 def cmd_profile_list(cache_profiles_path, output):
24     folder = cache_profiles_path
25     if os.path.exists(folder):
26         return [name for name in os.listdir(folder)
27                 if not os.path.isdir(os.path.join(folder, name))]
28     else:
29         output.info("No profiles defined")
30         return []
31 
32 
33 def cmd_profile_create(profile_name, cache_profiles_path, output, detect=False):
34     profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd(),
35                                     exists=False)
36     if os.path.exists(profile_path):
37         raise ConanException("Profile already exists")
38 
39     profile = Profile()
40     if detect:
41         settings = detect_defaults_settings(output)
42         for name, value in settings:
43             profile.settings[name] = value
44 
45     contents = profile.dumps()
46     save(profile_path, contents)
47 
48     if detect:
49         output.info("Profile created with detected settings: %s" % profile_path)
50     else:
51         output.info("Empty profile created: %s" % profile_path)
52     return profile_path
53 
54 
55 def cmd_profile_update(profile_name, key, value, cache_profiles_path):
56     first_key, rest_key = _get_profile_keys(key)
57 
58     profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)
59     if first_key == "settings":
60         profile.settings[rest_key] = value
61     elif first_key == "options":
62         tmp = OptionsValues([(rest_key, value)])
63         profile.options.update(tmp)
64     elif first_key == "env":
65         profile.env_values.update_replace(rest_key, value)
66     elif first_key == "build_requires":
67         raise ConanException("Edit the profile manually to change the build_requires")
68 
69     contents = profile.dumps()
70     profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())
71     save(profile_path, contents)
72 
73 
74 def cmd_profile_get(profile_name, key, cache_profiles_path):
75     first_key, rest_key = _get_profile_keys(key)
76     profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)
77     try:
78         if first_key == "settings":
79             return profile.settings[rest_key]
80         elif first_key == "options":
81             return dict(profile.options.as_list())[rest_key]
82         elif first_key == "env":
83             package = None
84             var = rest_key
85             if ":" in rest_key:
86                 package, var = rest_key.split(":")
87             return profile.env_values.data[package][var]
88         elif first_key == "build_requires":
89             raise ConanException("List the profile manually to see the build_requires")
90     except KeyError:
91         raise ConanException("Key not found: '%s'" % key)
92 
93 
94 def cmd_profile_delete_key(profile_name, key, cache_profiles_path):
95     first_key, rest_key = _get_profile_keys(key)
96     profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)
97 
98     try:
99         package, name = rest_key.split(":")
100     except ValueError:
101         package = None
102         name = rest_key
103 
104     try:
105         if first_key == "settings":
106             del profile.settings[rest_key]
107         elif first_key == "options":
108             profile.options.remove(name, package)
109         elif first_key == "env":
110             profile.env_values.remove(name, package)
111         elif first_key == "build_requires":
112             raise ConanException("Edit the profile manually to delete a build_require")
113     except KeyError:
114         raise ConanException("Profile key '%s' doesn't exist" % key)
115 
116     contents = profile.dumps()
117     profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())
118     save(profile_path, contents)
119
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/conans/client/cmd/profile.py b/conans/client/cmd/profile.py
--- a/conans/client/cmd/profile.py
+++ b/conans/client/cmd/profile.py
@@ -21,13 +21,18 @@
 
 
 def cmd_profile_list(cache_profiles_path, output):
-    folder = cache_profiles_path
-    if os.path.exists(folder):
-        return [name for name in os.listdir(folder)
-                if not os.path.isdir(os.path.join(folder, name))]
-    else:
+    profiles = []
+    if os.path.exists(cache_profiles_path):
+        for current_directory, _, files in os.walk(cache_profiles_path, followlinks=True):
+            for filename in files:
+                rel_path = os.path.relpath(os.path.join(current_directory, filename),
+                                           cache_profiles_path)
+                profiles.append(rel_path)
+
+    if not profiles:
         output.info("No profiles defined")
-        return []
+    profiles.sort()
+    return profiles
 
 
 def cmd_profile_create(profile_name, cache_profiles_path, output, detect=False):

{"golden_diff": "diff --git a/conans/client/cmd/profile.py b/conans/client/cmd/profile.py\n--- a/conans/client/cmd/profile.py\n+++ b/conans/client/cmd/profile.py\n@@ -21,13 +21,18 @@\n \n \n def cmd_profile_list(cache_profiles_path, output):\n-    folder = cache_profiles_path\n-    if os.path.exists(folder):\n-        return [name for name in os.listdir(folder)\n-                if not os.path.isdir(os.path.join(folder, name))]\n-    else:\n+    profiles = []\n+    if os.path.exists(cache_profiles_path):\n+        for current_directory, _, files in os.walk(cache_profiles_path, followlinks=True):\n+            for filename in files:\n+                rel_path = os.path.relpath(os.path.join(current_directory, filename),\n+                                           cache_profiles_path)\n+                profiles.append(rel_path)\n+\n+    if not profiles:\n         output.info(\"No profiles defined\")\n-        return []\n+    profiles.sort()\n+    return profiles\n \n \n def cmd_profile_create(profile_name, cache_profiles_path, output, detect=False):\n", "issue": "[question][suggestion] Listing profile should be recursive\nHello,\r\n\r\nI use multiple profiles, and those are organized in subdirectories:\r\n   + `~/.conan/profiles/application/x64_gcc6_app1`\r\n   + `~/.conan/profiles/application/x64_msvc_app1`\r\n   + `~/.conan/profiles/compilers/x64_gcc6`\r\n   + `~/.conan/profiles/compilers/x64_msvc`\r\n\r\nThe \"applications\" profile include other profiles etc. This works pretty well, so I assume \r\nusing subdirectory in profiles is supported and is not a problem.\r\n\r\nHowever, the `conan profile list` command does not list profiles contained in subdirectories.\r\nI believe it should recursively search for profile files rather than only list the files available directly in the `~/.conan/profiles` directory.\r\n\r\nI'm wondering if there is a particular reason why the search is limited to the `~/.conan/profiles` directory and if you'd be open to changing this behavior.\r\n\n", "before_files": [{"content": "import os\n\nfrom conans.client.conf.detect import detect_defaults_settings\nfrom conans.client.profile_loader import get_profile_path, read_profile\nfrom conans.errors import ConanException\nfrom conans.model.options import OptionsValues\nfrom conans.model.profile import Profile\nfrom conans.unicode import get_cwd\nfrom conans.util.files import save\n\n\ndef _get_profile_keys(key):\n    # settings.compiler.version => settings, compiler.version\n    tmp = key.split(\".\")\n    first_key = tmp[0]\n    rest_key = \".\".join(tmp[1:]) if len(tmp) > 1 else None\n    if first_key not in (\"build_requires\", \"settings\", \"options\", \"env\"):\n        raise ConanException(\"Invalid specified key: %s\" % key)\n\n    return first_key, rest_key\n\n\ndef cmd_profile_list(cache_profiles_path, output):\n    folder = cache_profiles_path\n    if os.path.exists(folder):\n        return [name for name in os.listdir(folder)\n                if not os.path.isdir(os.path.join(folder, name))]\n    else:\n        output.info(\"No profiles defined\")\n        return []\n\n\ndef cmd_profile_create(profile_name, cache_profiles_path, output, detect=False):\n    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd(),\n                                    exists=False)\n    if os.path.exists(profile_path):\n        raise ConanException(\"Profile already exists\")\n\n    profile = Profile()\n    if detect:\n        settings = detect_defaults_settings(output)\n        for name, value in settings:\n            profile.settings[name] = value\n\n    contents = profile.dumps()\n    save(profile_path, contents)\n\n    if detect:\n        output.info(\"Profile created with detected settings: %s\" % profile_path)\n    else:\n        output.info(\"Empty profile created: %s\" % profile_path)\n    return profile_path\n\n\ndef cmd_profile_update(profile_name, key, value, cache_profiles_path):\n    first_key, rest_key = _get_profile_keys(key)\n\n    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)\n    if first_key == \"settings\":\n        profile.settings[rest_key] = value\n    elif first_key == \"options\":\n        tmp = OptionsValues([(rest_key, value)])\n        profile.options.update(tmp)\n    elif first_key == \"env\":\n        profile.env_values.update_replace(rest_key, value)\n    elif first_key == \"build_requires\":\n        raise ConanException(\"Edit the profile manually to change the build_requires\")\n\n    contents = profile.dumps()\n    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())\n    save(profile_path, contents)\n\n\ndef cmd_profile_get(profile_name, key, cache_profiles_path):\n    first_key, rest_key = _get_profile_keys(key)\n    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)\n    try:\n        if first_key == \"settings\":\n            return profile.settings[rest_key]\n        elif first_key == \"options\":\n            return dict(profile.options.as_list())[rest_key]\n        elif first_key == \"env\":\n            package = None\n            var = rest_key\n            if \":\" in rest_key:\n                package, var = rest_key.split(\":\")\n            return profile.env_values.data[package][var]\n        elif first_key == \"build_requires\":\n            raise ConanException(\"List the profile manually to see the build_requires\")\n    except KeyError:\n        raise ConanException(\"Key not found: '%s'\" % key)\n\n\ndef cmd_profile_delete_key(profile_name, key, cache_profiles_path):\n    first_key, rest_key = _get_profile_keys(key)\n    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)\n\n    try:\n        package, name = rest_key.split(\":\")\n    except ValueError:\n        package = None\n        name = rest_key\n\n    try:\n        if first_key == \"settings\":\n            del profile.settings[rest_key]\n        elif first_key == \"options\":\n            profile.options.remove(name, package)\n        elif first_key == \"env\":\n            profile.env_values.remove(name, package)\n        elif first_key == \"build_requires\":\n            raise ConanException(\"Edit the profile manually to delete a build_require\")\n    except KeyError:\n        raise ConanException(\"Profile key '%s' doesn't exist\" % key)\n\n    contents = profile.dumps()\n    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())\n    save(profile_path, contents)\n", "path": "conans/client/cmd/profile.py"}], "after_files": [{"content": "import os\n\nfrom conans.client.conf.detect import detect_defaults_settings\nfrom conans.client.profile_loader import get_profile_path, read_profile\nfrom conans.errors import ConanException\nfrom conans.model.options import OptionsValues\nfrom conans.model.profile import Profile\nfrom conans.unicode import get_cwd\nfrom conans.util.files import save\n\n\ndef _get_profile_keys(key):\n    # settings.compiler.version => settings, compiler.version\n    tmp = key.split(\".\")\n    first_key = tmp[0]\n    rest_key = \".\".join(tmp[1:]) if len(tmp) > 1 else None\n    if first_key not in (\"build_requires\", \"settings\", \"options\", \"env\"):\n        raise ConanException(\"Invalid specified key: %s\" % key)\n\n    return first_key, rest_key\n\n\ndef cmd_profile_list(cache_profiles_path, output):\n    profiles = []\n    if os.path.exists(cache_profiles_path):\n        for current_directory, _, files in os.walk(cache_profiles_path, followlinks=True):\n            for filename in files:\n                rel_path = os.path.relpath(os.path.join(current_directory, filename),\n                                           cache_profiles_path)\n                profiles.append(rel_path)\n\n    if not profiles:\n        output.info(\"No profiles defined\")\n    profiles.sort()\n    return profiles\n\n\ndef cmd_profile_create(profile_name, cache_profiles_path, output, detect=False):\n    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd(),\n                                    exists=False)\n    if os.path.exists(profile_path):\n        raise ConanException(\"Profile already exists\")\n\n    profile = Profile()\n    if detect:\n        settings = detect_defaults_settings(output)\n        for name, value in settings:\n            profile.settings[name] = value\n\n    contents = profile.dumps()\n    save(profile_path, contents)\n\n    if detect:\n        output.info(\"Profile created with detected settings: %s\" % profile_path)\n    else:\n        output.info(\"Empty profile created: %s\" % profile_path)\n    return profile_path\n\n\ndef cmd_profile_update(profile_name, key, value, cache_profiles_path):\n    first_key, rest_key = _get_profile_keys(key)\n\n    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)\n    if first_key == \"settings\":\n        profile.settings[rest_key] = value\n    elif first_key == \"options\":\n        tmp = OptionsValues([(rest_key, value)])\n        profile.options.update(tmp)\n    elif first_key == \"env\":\n        profile.env_values.update_replace(rest_key, value)\n    elif first_key == \"build_requires\":\n        raise ConanException(\"Edit the profile manually to change the build_requires\")\n\n    contents = profile.dumps()\n    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())\n    save(profile_path, contents)\n\n\ndef cmd_profile_get(profile_name, key, cache_profiles_path):\n    first_key, rest_key = _get_profile_keys(key)\n    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)\n    try:\n        if first_key == \"settings\":\n            return profile.settings[rest_key]\n        elif first_key == \"options\":\n            return dict(profile.options.as_list())[rest_key]\n        elif first_key == \"env\":\n            package = None\n            var = rest_key\n            if \":\" in rest_key:\n                package, var = rest_key.split(\":\")\n            return profile.env_values.data[package][var]\n        elif first_key == \"build_requires\":\n            raise ConanException(\"List the profile manually to see the build_requires\")\n    except KeyError:\n        raise ConanException(\"Key not found: '%s'\" % key)\n\n\ndef cmd_profile_delete_key(profile_name, key, cache_profiles_path):\n    first_key, rest_key = _get_profile_keys(key)\n    profile, _ = read_profile(profile_name, get_cwd(), cache_profiles_path)\n\n    try:\n        package, name = rest_key.split(\":\")\n    except ValueError:\n        package = None\n        name = rest_key\n\n    try:\n        if first_key == \"settings\":\n            del profile.settings[rest_key]\n        elif first_key == \"options\":\n            profile.options.remove(name, package)\n        elif first_key == \"env\":\n            profile.env_values.remove(name, package)\n        elif first_key == \"build_requires\":\n            raise ConanException(\"Edit the profile manually to delete a build_require\")\n    except KeyError:\n        raise ConanException(\"Profile key '%s' doesn't exist\" % key)\n\n    contents = profile.dumps()\n    profile_path = get_profile_path(profile_name, cache_profiles_path, get_cwd())\n    save(profile_path, contents)\n", "path": "conans/client/cmd/profile.py"}]}