For example, assuming that x = filename.jpg, I want to get filename, where filename could be any file name (Let's assume the file name only contains [a-zA-Z0-9-_] to simplify.).
I saw x.substring(0, x.indexOf('.jpg')) on DZone Snippets, but wouldn't x.substring(0, x.length-4) perform better? Because, length is a property and doesn't do character checking whereas indexOf() is a function and does character checking.
Not sure what would perform faster but this would be more reliable when it comes to extension like .jpeg or .html
x.replace(/\.[^/.]+$/, "")
In node.js, the name of the file without the extension can be obtained as follows.
const path = require('path');
const filename = 'hello.html';
path.parse(filename).name; //=> "hello"
path.parse(filename).ext; //=> ".html"
path.parse(filename).base; //=> "hello.html"
Further explanation at Node.js documentation page.
If you know the length of the extension, you can use x.slice(0, -4) (where 4 is the three characters of the extension and the dot).
If you don't know the length #John Hartsock regex would be the right approach.
If you'd rather not use regular expressions, you can try this (less performant):
filename.split('.').slice(0, -1).join('.')
Note that it will fail on files without extension.
x.length-4 only accounts for extensions of 3 characters. What if you have filename.jpegor filename.pl?
EDIT:
To answer... sure, if you always have an extension of .jpg, x.length-4 would work just fine.
However, if you don't know the length of your extension, any of a number of solutions are better/more robust.
x = x.replace(/\..+$/, '');
OR
x = x.substring(0, x.lastIndexOf('.'));
OR
x = x.replace(/(.*)\.(.*?)$/, "$1");
OR (with the assumption filename only has one dot)
parts = x.match(/[^\.]+/);
x = parts[0];
OR (also with only one dot)
parts = x.split(".");
x = parts[0];
I like this one because it is a one liner which isn't too hard to read:
filename.substring(0, filename.lastIndexOf('.')) || filename
You can perhaps use the assumption that the last dot will be the extension delimiter.
var x = 'filename.jpg';
var f = x.substr(0, x.lastIndexOf('.'));
If file has no extension, it will return empty string. To fix that use this function
function removeExtension(filename){
var lastDotPosition = filename.lastIndexOf(".");
if (lastDotPosition === -1) return filename;
else return filename.substr(0, lastDotPosition);
}
In Node.js versions prior to 0.12.x:
path.basename(filename, path.extname(filename))
Of course this also works in 0.12.x and later.
I don't know if it's a valid option but I use this:
name = filename.split(".");
// trimming with pop()
name.pop();
// getting the name with join()
name.join('.'); // we split by '.' and we join by '.' to restore other eventual points.
It's not just one operation I know, but at least it should always work!
UPDATE: If you want a oneliner, here you are:
(name.split('.').slice(0, -1)).join('.')
This works, even when the delimiter is not present in the string.
String.prototype.beforeLastIndex = function (delimiter) {
return this.split(delimiter).slice(0,-1).join(delimiter) || this + ""
}
"image".beforeLastIndex(".") // "image"
"image.jpeg".beforeLastIndex(".") // "image"
"image.second.jpeg".beforeLastIndex(".") // "image.second"
"image.second.third.jpeg".beforeLastIndex(".") // "image.second.third"
Can also be used as a one-liner like this:
var filename = "this.is.a.filename.txt";
console.log(filename.split(".").slice(0,-1).join(".") || filename + "");
EDIT: This is a more efficient solution:
String.prototype.beforeLastIndex = function (delimiter) {
return this.substr(0,this.lastIndexOf(delimiter)) || this + ""
}
Another one-liner:
x.split(".").slice(0, -1).join(".")
Here's another regex-based solution:
filename.replace(/\.[^.$]+$/, '');
This should only chop off the last segment.
Simple one:
var n = str.lastIndexOf(".");
return n > -1 ? str.substr(0, n) : str;
The accepted answer strips the last extension part only (.jpeg), which might be a good choice in most cases.
I once had to strip all extensions (.tar.gz) and the file names were restricted to not contain dots (so 2015-01-01.backup.tar would not be a problem):
var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"
If you have to process a variable that contains the complete path (ex.: thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg") and you want to return just "filename" you can use:
theName = thePath.split("/").slice(-1).join().split(".").shift();
the result will be theName == "filename";
To try it write the following command into the console window of your chrome debugger:
window.location.pathname.split("/").slice(-1).join().split(".").shift()
If you have to process just the file name and its extension (ex.: theNameWithExt = "filename.jpg"):
theName = theNameWithExt.split(".").shift();
the result will be theName == "filename", the same as above;
Notes:
The first one is a little bit slower cause performes more
operations; but works in both cases, in other words it can extract
the file name without extension from a given string that contains a path or a file name with ex. While the second works only if the given variable contains a filename with ext like filename.ext but is a little bit quicker.
Both solutions work for both local and server files;
But I can't say nothing about neither performances comparison with other answers nor for browser or OS compatibility.
working snippet 1: the complete path
var thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg";
theName = thePath.split("/").slice(-1).join().split(".").shift();
alert(theName);
working snippet 2: the file name with extension
var theNameWithExt = "filename.jpg";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
working snippet 2: the file name with double extension
var theNameWithExt = "filename.tar.gz";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
Node.js remove extension from full path keeping directory
https://stackoverflow.com/a/31615711/895245 for example did path/hello.html -> hello, but if you want path/hello.html -> path/hello, you can use this:
#!/usr/bin/env node
const path = require('path');
const filename = 'path/hello.html';
const filename_parsed = path.parse(filename);
console.log(path.join(filename_parsed.dir, filename_parsed.name));
outputs directory as well:
path/hello
https://stackoverflow.com/a/36099196/895245 also achieves this, but I find this approach a bit more semantically pleasing.
Tested in Node.js v10.15.2.
Though it's pretty late, I will add another approach to get the filename without extension using plain old JS-
path.replace(path.substr(path.lastIndexOf('.')), '')
A straightforward answer, if you are using Node.js, is the one in the first comment.
My task was I need to delete an image in Cloudinary from the Node server and I just need to get the image name only.
Example:
const path = require("path")
const image=xyz.jpg;
const img= path.parse(image).name
console.log(img) // xyz
This is where regular expressions come in handy! Javascript's .replace() method will take a regular expression, and you can utilize that to accomplish what you want:
// assuming var x = filename.jpg or some extension
x = x.replace(/(.*)\.[^.]+$/, "$1");
You can use path to maneuver.
var MYPATH = '/User/HELLO/WORLD/FILENAME.js';
var MYEXT = '.js';
var fileName = path.basename(MYPATH, MYEXT);
var filePath = path.dirname(MYPATH) + '/' + fileName;
Output
> filePath
'/User/HELLO/WORLD/FILENAME'
> fileName
'FILENAME'
> MYPATH
'/User/HELLO/WORLD/FILENAME.js'
This is the code I use to remove the extension from a filename, without using either regex or indexOf (indexOf is not supported in IE8). It assumes that the extension is any text after the last '.' character.
It works for:
files without an extension: "myletter"
files with '.' in the name: "my.letter.txt"
unknown length of file extension: "my.letter.html"
Here's the code:
var filename = "my.letter.txt" // some filename
var substrings = filename.split('.'); // split the string at '.'
if (substrings.length == 1)
{
return filename; // there was no file extension, file was something like 'myfile'
}
else
{
var ext = substrings.pop(); // remove the last element
var name = substrings.join(""); // rejoin the remaining elements without separator
name = ([name, ext]).join("."); // readd the extension
return name;
}
I like to use the regex to do that. It's short and easy to understand.
for (const regexPattern of [
/\..+$/, // Find the first dot and all the content after it.
/\.[^/.]+$/ // Get the last dot and all the content after it.
]) {
console.log("myFont.ttf".replace(regexPattern, ""))
console.log("myFont.ttf.log".replace(regexPattern, ""))
}
/* output
myFont
myFont
myFont
myFont.ttf
*/
The above explanation may not be very rigorous. If you want to get a more accurate explanation can go to regex101 to check
\..+$
\.[^/.]+$
We might come across filename or file path with multiple extension suffix. Consider the following to trim them.
text = "/dir/path/filename.tar.gz"
output = text.replace(/(\.\w+)+$/,"")
result of output: "/dir/path/filename"
It solves the file extension problem especially when the input has multiple extensions.
Another one liner - we presume our file is a jpg picture >> ex: var yourStr = 'test.jpg';
yourStr = yourStr.slice(0, -4); // 'test'
x.slice(0, -(x.split('.').pop().length + 1));
name.split('.').slice(0, -1).join('.')
that's all enjoy your coding...
I would use something like x.substring(0, x.lastIndexOf('.')). If you're going for performance, don't go for javascript at all :-p No, one more statement really doesn't matter for 99.99999% of all purposes.
Related
I am having a little problem. I want to get the file name
(横 浜 プ レ _ 図 面 デ ー タ .pdf)
from the url below. I don't know how to use regex to find the file name.
Hope everybody help please.
https://reclaim-files-dev.s3.ap-northeast-1.amazonaws.com/attachment/横浜プレ_図面データ.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIASUJZK2B4ZLI77WWZ%2F20200303%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20200303T042736Z&X-Amz-Expires=300&X-Amz-Signature=b8b00cb04dbe5a73de8230327651636784a0c9d7979a5666e13b54d67f116703&X-Amz-SignedHeaders=host
Create an URL and let it parse:
const url = new URL(yourUrlString);
Filter the file name:
const fileName = url.pathname.replace(/^.*[\\\/]/, "");
If the filename always follows /attachment/ in the URL, and presumably is always followed with the ? and the rest of the parameters:
Assuming the entire url is assigned to urlString
let startIndex = urlString.indexOf("/attachment/");
let endIndex = urlString.indexOf("?");
let fileName = urlString.substring(startIndex, fileName);
This will find any filename regardless of file type (you mention pdf, but this would find files with other extensions).
var url = 'https://reclaim-files-dev.s3.ap-northeast-1.amazonaws.com/attachment/横浜プレ_図面データ.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIASUJZK2B4ZLI77WWZ%2F20200303%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20200303T042736Z&X-Amz-Expires=300&X-Amz-Signature=b8b00cb04dbe5a73de8230327651636784a0c9d7979a5666e13b54d67f116703&X-Amz-SignedHeaders=host';
var url2 = url.substring(0, url.indexOf('?X'));
console.log(url2.substring(url2.lastIndexOf('/') + 1));
I guess you can do this without regex
x = "https://reclaim-files-dev.s3.ap-northeast-1.amazonaws.com/attachment/横浜プレ_図面データ.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIASUJZK2B4ZLI77WWZ%2F20200303%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20200303T042736Z&X-Amz-Expires=300&X-Amz-Signature=b8b00cb04dbe5a73de8230327651636784a0c9d7979a5666e13b54d67f116703&X-Amz-SignedHeaders=host"
y = x.split('/')
["https:", "", "reclaim-files-dev.s3.ap-northeast-1.amazonaws.com", "attachment", "横浜プレ_図面データ.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&…979a5666e13b54d67f116703&X-Amz-SignedHeaders=host"]
your attachment will be in the 4th index
str = y[4].substr(0, y[4].indexOf('.pdf'))
If you are looking to get the file name from specifically this arrangement of a URL, then simply split by the first argument (?) and then split by forward slash. This will give you an array which you can reverse. The first element of this array will be your file name:
function get_file(url_string){
return url_string.split('?')[0].split('/').reverse()[0];
}
If you want to go a step further, you can then split the result by (.) in order to get the actual name and the file extension in a single step:
function get_file(url_string){
return url_string.split('?')[0].split('/').reverse()[0].split('.');
}
Note: as previously mentioned, this only works with your URL arrangement.
I have a file path as shown below.The last part (i.e. video2.mp4) is dynamically changed.I'm using Javascript/Typescript.
file:///data/user/0/com.sleep.app/files/sleep-videos/video2.mp4
Question: How to get the file:///data/user/0/com.sleep.app/files/sleep-videos/ part only from above string.
var string = 'file:///data/user/0/com.sleep.app/files/sleep-videos/video2.mp4';
var stringPart = string.substring(0,string.lastIndexOf("/")+1);
If only the filename changes try something like here
^(.+)/([^/]+)$
Try it at regexr. Your first group is the dirname, the second group the basename.
If you have further requirements/information (e.g. which tools you use), please refine your question.
var url = "file:///data/user/0/com.sleep.app/files/sleep-videos/video2.mp4";
url= url.split("/");
url.pop();
url = url.join("/");
New to ExtendScript and trying to finish an automation project for work.
I have a bunch of images that I am combining in photoshop via a script and need to open a image pairing based on an initial image. I know that the name of my paired file will be predictable up until the final character, at which point it will be any uppercase letter A-Z.
For example:
CH-14B1-SP-01-A can pairs with CH-14B1-SP-PV-01-A, but could also conceivably be paired with CH-14B1-SP-PV-01-B. Each paired file has an A-D replicate and we choose the best to be paired.
I have a script working that requires user input to decide what replicate to look for. I want to automate this. My code looks like this:
// ask user input for PV replicate letter
var repLetter =prompt("Which PV replicate would you like to use? (A.. B.. C.. etc.)");
// get the info out of the source doc
var fileName = srcDoc.name;
var docName = fileName.substring(0,fileName.length -4);
var filePath = srcDoc.path.toString();
var fileExt = fileName.substring(fileName.length -4, fileName.length);
var nameCheck = fileName.substring(0,fileName.indexOf("CH-14B1-SPI-"));
if (nameCheck <1)
{
var fileNum = fileName.substring(12,fileName.length -5) + repLetter;
// no underscore so we need to open it's namesake
// alert(nameCheck)
var filePair = filePath + "/PV/" + "CH-14B1-SPI-PV-" + fileNum + fileExt;
openThisFile(filePair)
Is there any way to make the var repLetter just accept any value at all?
Something like
var fileNum = fileName.substring(12,fileName.length -5) + [a-z];
I tried the above hoping it would do the trick (again very new to this) and I was told that "a" was undefined.
Your fault lies in the incorrect syntax in
var fileNum = fileName.substring(12,fileName.length -5) + [a-z];
... it's just bad syntax, you seem to be mixing GREP into JS. The error is issued because [...] indicates an array, which is valid to 'add' to a string, but the expression a-z ("a minus z") needs variables named a and z. I suppose you simply wanted some sort of wildcard here.
Circumvent the entire issue by reading a list of candidate files, based on the current file name. This is kind of hard to test locally because it requires lots of dummy files (and I'm not entirely sure I understand your procedure). However, the general idea of the following should be clear.
Rather than prompting for 'any' letter, it's more user friendly to show the available choices. I am not sure how you get the list of candidates, so I'll let you fill in that yourself. You need to adjust the getFiles call for this; currently, it reads the files from filePath, with a * after its name to pick up everything starting with nameCheck.
The found list of files is shown in a simple dialog with radio buttons to pick a file from. As it is, it only shows an alert, and if you press Cancel it does nothing.
Please note I have tested this inside InDesign, not Photoshop, as it's an easier test bed for scripts, and so it is possible some of the property names are off.
srcDoc = app.activeDocument;
var fileName = srcDoc.name;
var docName = fileName.substring(0,fileName.lastIndexOf('.'));
var filePath = srcDoc.filePath.toString();
var fileExt = fileName.substring(fileName.lastIndexOf('.')+1);
var nameCheck = fileName.substring(0,fileName.indexOf("CH-14B1-SPI-"));
var filelist = Folder(filePath).getFiles (nameCheck+'*.'+fileExt).sort();
if (filelist.length == 0)
{
alert ('No files found matching '+nameCheck+'*.'+fileExt);
} else
{
var fileDialog = app.dialogs.add({name:"Choose a file", canCancel:true});
with (fileDialog)
{
with(dialogColumns.add())
{
with (fileSel = radiobuttonGroups.add())
{
radiobuttonControls.add({staticLabel:filelist[i].name,checkedState:i==0});
}
}
}
if (fileDialog.show() == true)
{
alert ('you picked '+filelist[fileSel.selectedButton].name);
}
}
For example I have a url like:
ftp://xxx:xxx#ftp.example.com/BigFile.zip
How can I get example.com from this url using javascript/jquery?
You can get the browser to parse the URL for you like this :
var a = document.createElement('a');
a.href = 'ftp://xxx:xxx#ftp.example.com/BigFile.zip';
var host = a.hostname;
That gets you the hostname, which in this case would be ftp.example.com, if for some reason you have to remove the subdomain, you can do
var domain = host.split('.');
domain.shift();
var domain = domain.join('.');
FIDDLE
Here's the different parts to a URL -> https://developer.mozilla.org/en-US/docs/Web/API/Location#wikiArticle
Here is using javascript RegExp
input = "ftp://xxx:xxx#ftp.example.com/BigFile.zip";
pattern = new RegExp(/ftp:\/\/\S+?#\S+?\.([^\/]+)/);
match = pattern.exec(input);
alert(match[1]);
You can also use i at the end of regex to make it case insensitive.
pattern = new RegExp(/ftp:\/\/\S+?#\S+?\.([^\/]+)/i);
You can use jquery like this:
var url = "ftp://xxx:xxx#ftp.example.com/BigFile.zip";
var ahref = $('<a>', { href:url } )[0]; // create an <a> element
var host = ahref.hostname.split('.').slice(1).join('.'); // example.com
You can have a regex to do this for you.
url = 'ftp://xxx:xxx#ftp.example.com/BigFile.zip'
base_address = url.match(/#.*\//)[0];
base_address = base_address.substring(1, base_address.length-1)
This would contain ftp.example.com though. You can fine tune it as per your need.
I just wanted to try/add something different (can't bet for performance or the general solution, but it works and hey ! without DOM/regexp involved):
var x="ftp://xxx:xxx#ftp.example.com/BigFile.zip"
console.log((x.split(".")[1]+ "." + x.split(".")[2]).split("/")[0]);
For the given case can be shortest since always will be ".com"
console.log(x.split(".")[1]+ ".com");
Another (messy) approach (and will work with .com.something:
console.log(x.substring((x.indexOf("#ftp"))+5,x.indexOf(x.split("/")[3])-1));
And well on this we're dependend about having "#ftp" and the slashes "/" (at least 3 of them or one after the .com.something) for example would not work with: ftp://xxx:xxx#ftp.example.com
Last update This will be my best
without DOM/RegExp, nicer (but also confusing) that the previous ones
solves the problem about having or don't the slashes,
still dependant on having "#ftp." in the string.
works with .com.something.whatever
(function (splittedString){
//this is a bit nicer, no regExp, no DOM, avoid abuse of "split"
//method over and over the same string
//check if we have a "/"
if(splittedString.indexOf("/")>=0){
//split one more time only to get what we want.
return (console.log(splittedString.split("/")[0]));
}
else{
return (console.log(splittedString));//else we have what we want
}
})(x.split("#ftp.")[1]);
As always it depends how maintainable you want your code to be, I just wanted to honor the affirmation about there's more than one way to code something. My answer for sure is not the best, but based on it you could improve your question.
I am trying to write a small jQuery / javascript function that searches through all the links on a page, identifies the type of file to which the tag links, and then adds an appropriate class. The purpose of this task is to style the links depending on the type of file at the other end of the link.
So far I have this:
$(document).ready(function(){
$('#rt-mainbody a').each(function(){
linkURL = $(this).attr('href');
var match = linkURL.match("^.*\.(pdf|PDF)$");
if(match != null){$(this).addClass('pdf');}
});
});
Fiddle me this.
And then I would continue the concept to identify, for example, spreadsheet files, Word documents, text files, jpgs, etc.
it works... but the thing is, to me this is super clunky because I have completely botched it together from odds and sods I've found around SO and the internet - I'm sure there must be a neater, more efficient, more readable way of doing this but I have no idea what it might be. Can someone give it a spit and polish for me, please?
Ideally the function should detect (a) that the extension is at the end of the href string, and (b) that the extension is preceded by a dot.
Thanks! :)
EDIT
Wow! Such a response! :) Thanks guys!
When I saw the method using simply the selector it was a bit of a facepalm moment - however the end user I am building this app for is linking to PDFs (and potentially other MIMEs) on a multitude of resource websites and has no control over the case usage of the filenames to which they'll be linking... using the selector is clearly not the way to go because the result would be so inconsistent.
EDIT
And the grand prize goes to #Dave Stein!! :D
The solution I will adopt is a "set it and leave it" script (fiddle me that) which will accommodate any extension, regardless of case, and all I need to do is tweak the CSS for each reasonable eventuality.
It's actually nice to learn that I was already fairly close to the best solution already... more through good luck than good judgement though XD
Well you don't want to use regex to search strings so I like that you narrowed it to just links. I saved off $(this) so you don't have to double call it. I also changed the regex so it's case insensitive. And lastly I made sure that the class is adding what the match was. This accomplish what you want?
$(document).ready(function(){
$('#rt-mainbody a').each(function(){
var $link = $(this),
linkURL = $link.attr('href'),
// I can't remember offhand but I think some extensions have numbers too
match = linkURL.match( /^.*\.([a-z0-9]+)$/i );
if( match != null ){
$link.addClass( match[1].toLowerCase() );
}
});
});
Oh and I almost forgot, I made sure linkURL was no longer global. :)
"Attribute ends with" selector:
$('#rt-mainbody a[href$=".pdf"], #rt-mainbody a[href$=".PDF"]').addClass('pdf')
EDIT: Or more generally and flexibly:
var types = {
doc: ['doc', 'docx'],
pdf: ['pdf'],
// ...
};
function addLinkClasses(ancestor, types) {
var $ancestor = $(ancestor);
$.each(types, function(type, extensions) {
selector = $.map(extensions, function(extension) {
return 'a[href$=".' + extension + '"]';
}).join(', ');
$ancestor.find(selector).addClass(type);
});
}
addLinkClasses('#rt-mainbody', types);
This is case sensitive, so I suggest you canonicalise all extensions to lowercase on your server.
Regex should be /^.*\.(pdf)$/i .
You can use this in your selector (to find all links to pdf files)
a[href$=".pdf"]
use this regex (without quotes):
/\.(pdf|doc)$/i
this regex matches (case insensitive) anything that ends with .pdf, .doc etc.
for dynamic class:
var match = linkURL.match(/\.(pdf|doc)$/i);
match = match ? match[1].toLowerCase() : null;
if (match != null) {
$(this).addClass(match);
}
Another answer, building off of #Amadan is:
var extensions = [
'pdf',
'jpg',
'doc'
];
$.each( extensions, function( i, v) {
$('#rt-mainbody').find( 'a[href$=".' + v + '"], a[href$=".' + v.toUpperCase() + '"]')
.addClass( extension );
});
The onyl suggestion I would make is that you can change your match to inspect what is the file extension instead of having to do a different regex search for each possible file extension:
var linkURL = $(this).attr('href'); //<--you were accidentally declared linkURL as a global BTW.
var match = linkURL.match(/\.(.*)$/);
if(match != null){
//we can extract the part between the parens in our regex
var ext = match[1].toLowerCase()
switch(ext){
case 'pdf': $(this).addClass('pdf'); break;
case 'jpg': $(this).addClass('jpg'); break;
//...
}
}
This switch statement mostly useful if you want the option of using class names that are different from your file extensions. If the file extension is always the same you can consider changing the regex to something that fits the file extensions you want
/\.(pdf|jpg|txt)$/i //i for "case insensitive"
and then just do
var ext = match[1].toLowerCase()
$(this).addClass(ext);