diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 1d01c0d54a..b063ae02f2 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -107,6 +107,7 @@ copy = Copy
 copy_generic = Copy to clipboard
 copy_url = Copy URL
 copy_hash = Copy hash
+copy_path = Copy path
 copy_content = Copy content
 copy_branch = Copy branch name
 copy_success = Copied!
diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl
index 230e49752f..1c73be9fb9 100644
--- a/templates/repo/diff/box.tmpl
+++ b/templates/repo/diff/box.tmpl
@@ -130,7 +130,7 @@
 								</div>
 								<span class="file tw-flex tw-items-center tw-font-mono tw-flex-1"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}</a>
 									{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
-									<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}" data-tooltip-content="{{ctx.Locale.Tr "copy_generic"}}" aria-label="{{ctx.Locale.Tr "copy_generic"}}">{{svg "octicon-copy" 14}}</button>
+										<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
 									{{if $file.IsGenerated}}
 										<span class="ui label">{{ctx.Locale.Tr "repo.diff.generated"}}</span>
 									{{end}}
diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl
index 5fa31f15c2..9cbdef53ca 100644
--- a/templates/repo/home.tmpl
+++ b/templates/repo/home.tmpl
@@ -113,6 +113,7 @@
 							<span class="breadcrumb-divider">/</span>
 							{{- if eq $i $l -}}
 								<span class="active section" title="{{$v}}">{{$v}}</span>
+								<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$.TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
 							{{- else -}}
 								{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
 							{{- end -}}
diff --git a/tests/e2e/clipboard-copy.test.e2e.ts b/tests/e2e/clipboard-copy.test.e2e.ts
new file mode 100644
index 0000000000..5d59f5b13c
--- /dev/null
+++ b/tests/e2e/clipboard-copy.test.e2e.ts
@@ -0,0 +1,33 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// @watch start
+// templates/repo/home.tmpl
+// templates/repo/diff/box.tmpl
+// web_src/js/features/clipboard.js
+// @watch end
+
+import {expect} from '@playwright/test';
+import {test} from './utils_e2e.ts';
+
+test.use({
+  permissions: ['clipboard-write'],
+});
+
+test('copy src file path to clipboard', async ({page}) => {
+  const response = await page.goto('/user2/repo1/src/branch/master/README.md');
+  expect(response?.status()).toBe(200);
+
+  await page.click('[data-clipboard-text]');
+  const clipboardText = await page.evaluate(() => navigator.clipboard.readText());
+  expect(clipboardText).toContain('README.md');
+});
+
+test('copy diff file path to clipboard', async ({page}) => {
+  const response = await page.goto('/user2/repo1/src/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d/README.md');
+  expect(response?.status()).toBe(200);
+
+  await page.click('[data-clipboard-text]');
+  const clipboardText = await page.evaluate(() => navigator.clipboard.readText());
+  expect(clipboardText).toContain('README.md');
+});