Why so difficult?
𝐀 = url.split('#')[0].split('?')[0].split('/').pop();
// Returns "file.name.ext"
𝐁 = url.split('#')[0].split('?')[0].split('/').pop().split('.')[0];
// Returns "file"; To handle multiple dots, use the last method below
The RegEx below will normally result in the same output as from the above, but it will return an empty string if the URL is significantly malformed.
𝐂 = (url.match(/^\w+:(\/+([^\/#?\s]+)){2,}(#|\?|$)/)||[])[2]||'';
// Returns an empty string for relative URLs, unlike the original approach
𝐃 = (url.match(/^\w+:(\/+([^\/#?\s]+)){2,}/)||[])[2]||'';
// Ignores trailing slashes (e.g., ".../posts/?a#b" results "posts")
𝐄 = ((url.match(/^\w+:(\/+([^\/#?\s]+)){2,}/)||[])[2]?.match(/^(.*?)(\.+[^.]*)?$/)||[])[1]||'';
// Removes the extension from the output of the 𝐃.
The 𝐀, 𝐂, 𝐃 returns file😃.name from:
my://host/path=&%dir///file😃.name?q=1/2&3=&#a/?b//?
The 𝐃 also returns dir.name from:
my://host/path=&%dir///dir.name/?not/these/#/ones//?
The 𝐄 is similar to the 𝐃 but returns file.name.dots from:
my://host/path=&%dir///file.name.dots..ext?q=1/2&3=&#a/?b//?
First Edit (Sep 2023) :
- Changed processing order because RFC 3986 explicitly allows fragments to have unencoded slashes. Now it handles fine even when the query("search" in JS) includes unencoded slashes(which obviously should be encoded).
- This means it properly handles any form of URL that most browsers can recognize.
- The RegEx methods have been added which include a very basic validity test. Similar concept to the original one but use a different approach.
Second Edit (Jun 2025) :
- Methods have been added to exclude extensions. Thanks to @Dan Froberg.
Try to test your URL by entering below. The 𝐃 ignores trailing slashes as described above. Please comment if any RegEx method doesn't properly handle any valid URL.
<style>*{margin:0;padding:0;box-sizing:border-box;border:none;}input{display:block;margin:.2em auto 0;padding:.8em 1.2em;width:calc(100% - 5px);background:#f8f8f8;border-radius:1em;font-size:75%;}p{margin:.8em auto 1em;padding-left:.5em;font-size:90%;color:#0008}p::after{content:attr(title);margin-left:.5em;padding:.3em;background:#fe8;border-radius:.5em;font-weight:800;color:#000;}</style><input value="my://host/path=&%dir///file😃.name..ext?q=1/2&3=&#a/?b//?" id="input"><p>𝐀</p><p>𝐁</p><p>𝐂</p><p>𝐃</p><p>𝐄</p>
<script>
((input = document.querySelector('input'), output = document.querySelectorAll('p')) => {
const getFilename = _=> {
output[0].title = input.value.split('#')[0].split('?')[0].split('/').pop();
output[1].title = input.value.split('#')[0].split('?')[0].split('/').pop().split('.')[0];
output[2].title = (input.value.match(/^\w+:(\/+([^\/#?\s]+)){2,}(#|\?|$)/)||[])[2]||'';
output[3].title = (input.value.match(/^\w+:(\/+([^\/#?\s]+)){2,}/)||[])[2]||'';
output[4].title = ((input.value.match(/^\w+:(\/+([^\/#?\s]+)){2,}/)||[])[2]?.match(/^(.*?)(\.+[^.]*)?$/)||[])[1]||'';
};
getFilename();
input.addEventListener('input', getFilename);
input.select();
})();
</script>