Comment découper une extension de fichier à partir d'une chaîne en JavaScript?

295

Par exemple, en supposant que x = filename.jpgje veux obtenir filename, où filenamepourrait être n'importe quel nom de fichier (supposons que le nom de fichier ne contienne que [a-zA-Z0-9-_] pour simplifier.).

J'ai vu x.substring(0, x.indexOf('.jpg'))sur DZone Snippets , mais je n'aurais pas x.substring(0, x.length-4)mieux performé ? Parce que, lengthest une propriété et ne vérifie pas les caractères alors que indexOf()c'est une fonction et vérifie les caractères.

ma11hew28
la source
À peu près la même chose que stackoverflow.com/questions/1991608/… . Et à moins que vous n'en fassiez beaucoup, le souci de l'efficacité est l'optimisation prématurée.
L'Archétype Paul
À l'ère d'ES6, consultez également le module Path - au cas où vous utilisez nodejs ou une transpilation appropriée
Frank Nocke

Réponses:

173

Si vous connaissez la longueur de l'extension, vous pouvez utiliser x.slice(0, -4)(où 4 représente les trois caractères de l'extension et le point).

Si vous ne connaissez pas la longueur des expressions régulières @John Hartsock serait la bonne approche.

Si vous préférez ne pas utiliser d'expressions régulières, vous pouvez essayer ceci (moins performant):

filename.split('.').slice(0, -1).join('.')

Notez qu'il échouera sur les fichiers sans extension.

Marek Sapota
la source
J'aime le mieux cette solution. Il est propre et je peux l'utiliser car je sais que l'extension du fichier est toujours .jpg. Je cherchais quelque chose comme Ruby x[0..-5], et a x.slice(0, -4)fière allure! Merci! Et merci à tous les autres pour toutes les autres alternatives robustes fournies!
ma11hew28
22
ce n'est pas la solution optimale, veuillez vérifier les autres solutions ci-dessous.
bunjeeb
8
Et si vous n'êtes pas sûr à 100% de la longueur de l'extension, alors ne faites pas ceci: "picture.jpeg".slice(0, -4)-> "image".
basic6
13
C'est une solution dangereuse, car vous ne connaissez pas vraiment la longueur du format.
Coder
"Si vous connaissez la durée de l'extension" Cela fait des décennies que cette hypothèse est acceptable. Ne l'utilisez plus.
Alexander - Réintègre Monica
454

Je ne sais pas ce qui fonctionnerait plus rapidement, mais ce serait plus fiable en ce qui concerne l'extension comme .jpegou.html

x.replace(/\.[^/.]+$/, "")
John Hartsock
la source
15
Vous voulez sans doute aussi disallow / comme séparateur de chemin, de sorte que le regexp est /\.[^/.]+$/
gsnedders
Cela fonctionne pour n'importe quelle longueur d'extension de fichier (.txt ou .html ou .htaccess) et permet également au nom de fichier de contenir des points (.) Supplémentaires. Il ne gérerait pas par exemple .tar.gz en raison de l'extension elle-même contenant un point. Il est plus courant qu'un nom de fichier contienne des périodes supplémentaires qu'une extension de fichier. Merci!
Steve Seeger
2
@Vik Il y a une différence entre la «bonne réponse» et la réponse acceptée. Une réponse acceptée est juste la réponse qui a été utile à celui qui a posé la question.
Steven
4
Je suppose qu'il peut y avoir des problèmes avec la plate-forme Windows car il peut y avoir des barres obliques inverses. Donc, l'expression rationnelle doit être /\.[^/\\.[+$/.
Alex Chuev
1
@ElgsQianChen voici un excellent outil pour vous aider à répondre à votre question regexr.com
John Hartsock
281

Dans node.js , le nom du fichier sans l'extension peut être obtenu comme suit.

const path = require('path');
const filename = 'hello.html';

path.parse(filename).name; // hello
path.parse(filename).ext;  // .html

Plus d'explications sur la page de documentation de Node.js.

Jibesh Patra
la source
2
Ce dont vous parlez @kaasdude .... cette méthode supprime efficacement l'extension sur le nœud., Ne savez pas ce que vous vouliez exprimer, mais cette méthode fonctionne perles.
Erick
1
Cette réponse est assez limitée au nœud côté serveur. Si vous essayez de l'utiliser dans le code React, il ne semble pas importer.
Charlie
1
si vous souhaitez supprimer une extension d'un chemin d'accès comprenant les répertoires, vous pouvez le faire var parsed = path.parse(filename)suivi de path.join(parsed.dir, parsed.name).
Jespertheend
Une autre possibilité est let base = path.basename( file_path, path.extname( file_path ) ).
bicarlsen
116

x.length-4ne prend en compte que les extensions de 3 caractères. Et si vous avez filename.jpegou filename.pl?

ÉDITER:

Pour répondre ... bien sûr, si vous avez toujours une extension de .jpg, x.length-4cela fonctionnerait très bien.

Cependant, si vous ne connaissez pas la longueur de votre extension, l'une des nombreuses solutions est meilleure / plus robuste.

x = x.replace(/\..+$/, '');

OU

x = x.substring(0, x.lastIndexOf('.'));

OU

x = x.replace(/(.*)\.(.*?)$/, "$1");

OU (avec l'hypothèse que le nom de fichier n'a qu'un seul point)

parts = x.match(/[^\.]+/);
x = parts[0];

OU (également avec un seul point)

parts = x.split(".");
x = parts[0];
Jeff B
la source
12
?? Vous pouvez avoir un nom de fichier ex: "summer.family.jpg" dans ce cas, split ('.') [0] ne renverra qu'un nom de fichier partiel. Je supprimerais celui-là de la réponse, ou j'indiquerais clairement sous le problème de cet exemple. @basarat ...
Roko C. Buljan
Quelque chose que je fais fréquemment en ce qui concerne le fractionnement des pièces:var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join(".");
radicand
x.split (".") ne devrait même pas être considéré comme une réponse. Je sais que j'utilise un '.' dans presque toutes mes conventions de dénomination de fichier, c'est-à-dire 'survey.controller.js' ou 'my.family.jpg'.
Lee Brindley
@ Lee2808: D'où l'avertissement d'un seul point. Ceci est simplement destiné à montrer qu'il existe un certain nombre d'approches, selon l'application. J'utiliserais certainement l'une des autres méthodes dans presque tous les cas.
Jeff B
x = x.substr(0, x.lastIndexOf('.'));- tu voulais dire x = x.substring(0, x.lastIndexOf('.'));?
Dziad Borowy
39

Vous pouvez peut-être utiliser l'hypothèse que le dernier point sera le délimiteur d'extension.

var x = 'filename.jpg';
var f = x.substr(0, x.lastIndexOf('.'));

Si le fichier n'a pas d'extension, il renverra une chaîne vide. Pour résoudre ce problème, utilisez cette fonction

function removeExtension(filename){
    var lastDotPosition = filename.lastIndexOf(".");
    if (lastDotPosition === -1) return filename;
    else return filename.substr(0, lastDotPosition);
}
Martin Algesten
la source
Attention, cela échoue s'il n'y a aucune extension de nom de fichier. Vous vous retrouvez avec une chaîne vide.
Brad
18
Version plus courte qui ne compte aucun point. var f = x.substr(0, x.lastIndexOf('.')) || x;Cela fonctionne car une chaîne vide est fausse, donc elle retourne x.
Jonathan Rowny
22

J'aime celui-ci car c'est un liner qui n'est pas trop difficile à lire:

filename.substring(0, filename.lastIndexOf('.')) || filename
jakubiszon
la source
17

Dans les versions de Node.js antérieures à 0.12.x:

path.basename(filename, path.extname(filename))

Bien sûr, cela fonctionne également dans 0.12.x et versions ultérieures.

blah238
la source
La path.parseréponse est plus simple.
Dan Dascalescu
12

Cela fonctionne, même lorsque le délimiteur n'est pas présent dans la chaîne.

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"

Peut également être utilisé comme une doublure comme ceci:

var filename = "this.is.a.filename.txt";
console.log(filename.split(".").slice(0,-1).join(".") || filename + "");

EDIT: Ceci est une solution plus efficace:

String.prototype.beforeLastIndex = function (delimiter) {
    return this.substr(0,this.lastIndexOf(delimiter)) || this + ""
}
Andrew Plank
la source
10

Je ne sais pas si c'est une option valide mais j'utilise ceci:

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.

Ce n'est pas seulement une opération que je connais, mais au moins cela devrait toujours fonctionner!

MISE À JOUR: Si vous voulez un oneliner, vous êtes ici:

(name.split('.').slice(0, -1)).join('.')

Giacomo Cerquone
la source
1
Ce ne doit pas être name.join ('') mais name.join ('.'). Vous vous séparez par point mais vous vous joignez par virgule, donc hello.name.txtretournehello, name
Evil
7

Un autre doublure:

x.split(".").slice(0, -1).join(".")
Jacob Bundgaard
la source
7

Voici une autre solution basée sur regex:

filename.replace(/\.[^.$]+$/, '');

Cela ne devrait couper que le dernier segment.

Chad Johnson
la source
7

Simple:

var n = str.lastIndexOf(".");
return n > -1 ? str.substr(0, n) : str;
Dugh
la source
6

La réponse acceptée ne retire que la dernière partie d'extension ( .jpeg), ce qui peut être un bon choix dans la plupart des cas.

Une fois, j'ai dû supprimer toutes les extensions ( .tar.gz) et les noms de fichiers ont été restreints pour ne pas contenir de points (ce 2015-01-01.backup.tarne serait donc pas un problème):

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");
basic6
la source
4
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"
Oui
la source
C'est la seule méthode jusqu'à présent qui fonctionne pour les chemins complets: path/name.ext-> paht/nameau lieu de simplement revenir name, mais je préfère faire avec fs.parsebien qu'elle soit un peu plus verbeuse: stackoverflow.com/a/59576950/895245
Ciro Santilli 郝海东 冠状 病六四 事件 法轮功
3

Si vous devez traiter une variable qui contient le chemin complet (ex. thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg") Et que vous souhaitez retourner uniquement "nom de fichier", vous pouvez utiliser:

theName = thePath.split("/").slice(-1).join().split(".").shift();

le résultat sera theName == "filename" ;

Pour l'essayer, écrivez la commande suivante dans la fenêtre de console de votre débogueur Chrome: window.location.pathname.split("/").slice(-1).join().split(".").shift()

Si vous ne devez traiter que le nom du fichier et son extension (ex. theNameWithExt = "filename.jpg"):

theName = theNameWithExt.split(".").shift();

le résultat sera theName == "filename" , le même que ci-dessus;

Remarques:

  1. Le premier est un peu plus lent car il effectue plus d'opérations; mais fonctionne dans les deux cas, en d'autres termes, il peut extraire le nom de fichier sans extension d'une chaîne donnée qui contient un chemin ou un nom de fichier avec ex. Alors que le second ne fonctionne que si la variable donnée contient un nom de fichier avec ext comme filename.ext mais est un peu plus rapide.
  2. Les deux solutions fonctionnent pour les fichiers locaux et serveur;

Mais je ne peux rien dire sur la comparaison des performances avec les autres réponses ni sur la compatibilité du navigateur ou du système d'exploitation.

extrait de travail 1: le chemin complet

var thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg";
theName = thePath.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

extrait de travail 2: le nom du fichier avec l'extension

var theNameWithExt = "filename.jpg";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

extrait de travail 2: le nom du fichier avec double extension

var theNameWithExt = "filename.tar.gz";
theName = theNameWithExt.split("/").slice(-1).join().split(".").shift();
alert(theName);
  

Willy Wonka
la source
3

Bien qu'il soit assez tard, j'ajouterai une autre approche pour obtenir le nom de fichier sans extension en utilisant du vieux JS simple

path.replace(path.substr(path.lastIndexOf('.')), '')

Munim Dibosh
la source
ou path.split('.').pop()pour des extensions de fichier en une partie
mixdev
Il essayait en fait d'obtenir le nom du fichier, pas l'extension!
Munim Dibosh du
3

Node.js supprime l'extension du répertoire complet de conservation des chemins

https://stackoverflow.com/a/31615711/895245 par exemple a fait path/hello.html-> hello, mais si vous voulez path/hello.html-> path/hello, vous pouvez utiliser ceci:

#!/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));

répertoire de sortie également:

path/hello

https://stackoverflow.com/a/36099196/895245 y parvient également, mais je trouve cette approche un peu plus sémantiquement agréable.

Testé dans Node.js v10.15.2.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
0

C'est là que les expressions régulières sont utiles! La .replace()méthode Javascript prendra une expression régulière, et vous pouvez l'utiliser pour accomplir ce que vous voulez:

// assuming var x = filename.jpg or some extension
x = x.replace(/(.*)\.[^.]+$/, "$1");
Alex
la source
0

Un autre liner - nous supposons que notre fichier est une image jpg >> ex: var yourStr = 'test.jpg';

    yourStr = yourStr.slice(0, -4); // 'test'
SorinN
la source
0

Vous pouvez utiliser pathpour manœuvrer.

var MYPATH = '/User/HELLO/WORLD/FILENAME.js';
var MYEXT = '.js';
var fileName = path.basename(MYPATH, MYEXT);
var filePath = path.dirname(MYPATH) + '/' + fileName;

Production

> filePath
'/User/HELLO/WORLD/FILENAME'
> fileName
'FILENAME'
> MYPATH
'/User/HELLO/WORLD/FILENAME.js'
Alan Dong
la source
0
x.slice(0, -(x.split('.').pop().length + 1));
ishandutta2007
la source
0

C'est le code que j'utilise pour supprimer l'extension d'un nom de fichier, sans utiliser ni regex ni indexOf (indexOf n'est pas pris en charge dans IE8). Il suppose que l'extension est un texte après le dernier '.' personnage.

Cela fonctionne pour:

  • fichiers sans extension: "myletter"
  • fichiers avec '.' dans le nom: "my.letter.txt"
  • longueur d'extension de fichier inconnue: "my.letter.html"

Voici le 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;
}
Little Brain
la source
échoue avec hello.tar.gz, la sortie est hellotar.
Asif Ali
#AsifAli merci vous avez raison, j'ai oublié de lire l'extension du fichier. J'ai mis à jour la réponse, j'espère que cela fonctionne maintenant.
Little Brain
-3

J'utiliserais quelque chose comme x.substring (0, x.lastIndexOf ('.')). Si vous optez pour les performances, n'utilisez pas du tout le javascript :-p Non, une autre déclaration n'a vraiment aucune importance pour 99,99999% de tous les usages.

Lucas Moeskops
la source
2
"Si vous optez pour la performance, n'utilisez pas du tout le javascript" - Que proposez-vous d'autre à utiliser dans les applications Web ..?
TJ
Il ne mentionne pas les applications Web.
Lucas Moeskops
1
Cette question a été posée et la réponse a été publiée en 2010, il y a 7 ans, et JavaScript n'était pratiquement utilisé que dans les applications Web. (Node venait de naître, il n'avait même pas de guide ou de MNP à l'époque)
TJ
;-) Néanmoins, si les performances sont importantes pour des tâches comme celle-ci, vous pouvez envisager de le faire sur le backend et de traiter les résultats sur le frontend.
Lucas Moeskops