¿Cómo recortar una extensión de archivo de una cadena en JavaScript?

295

Por ejemplo, suponiendo que x = filename.jpg, quiero llegar filename, dónde filenamepodría estar cualquier nombre de archivo (Supongamos que el nombre del archivo solo contiene [a-zA-Z0-9-_] para simplificar).

Vi x.substring(0, x.indexOf('.jpg'))en DZone Snippets , pero ¿no x.substring(0, x.length-4)funcionaría mejor? Porque, lengthes una propiedad y no realiza la comprobación de caracteres, mientras que indexOf()es una función y realiza la comprobación de caracteres.

ma11hew28
fuente
Casi lo mismo que stackoverflow.com/questions/1991608/… . Y a menos que haga muchos de estos, preocuparse por la eficiencia es la optimización prematura.
El arquetípico Paul
En la era de ES6, vea también el módulo Path , en caso de que esté usando nodejs o una transpilación adecuada
Frank Nocke el

Respuestas:

173

Si conoce la longitud de la extensión, puede usarla x.slice(0, -4)(donde 4 son los tres caracteres de la extensión y el punto).

Si no conoce la longitud, la expresión regular de @John Hartsock sería el enfoque correcto.

Si prefiere no usar expresiones regulares, puede intentar esto (menos rendimiento):

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

Tenga en cuenta que fallará en archivos sin extensión.

Marek Sapota
fuente
Me gusta esta solución lo mejor. Está limpio, y puedo usarlo porque sé que la extensión del archivo es siempre .jpg. Estaba buscando algo como Ruby's x[0..-5], ¡y se x.slice(0, -4)ve genial! ¡Gracias! ¡Y gracias a todos los demás por todas las otras alternativas robustas proporcionadas!
ma11hew28
22
esta no es la solución óptima, verifique otras soluciones a continuación.
bunjeeb
8
Y si no está 100% seguro de la longitud de la extensión, no haga esto: "picture.jpeg".slice(0, -4)-> "imagen".
basic6
13
Esta es una solución peligrosa, porque realmente no conoce la longitud del formato.
Codificador
"Si conoce la longitud de la extensión" Han pasado décadas desde que se hizo una suposición aceptable. No uses esto más.
Alexander - Restablece a Mónica el
454

No estoy seguro de qué funcionaría más rápido, pero esto sería más confiable cuando se trata de extensiones como .jpego.html

x.replace(/\.[^/.]+$/, "")
John Hartsock
fuente
15
Probablemente también desee no permitir / como un separador de ruta, por lo que la expresión regular es /\.[^/.font>+$/
gsnedders
Esto funciona para cualquier longitud de extensión de archivo (.txt o .html o .htaccess) y también permite que el nombre del archivo contenga caracteres de punto (.) Adicionales. No manejaría, por ejemplo, .tar.gz debido a que la extensión misma contiene un punto. Es más común que un nombre de archivo contenga períodos adicionales que una extensión de archivo. ¡Gracias!
Steve Seeger
2
@Vik Hay una diferencia entre la 'respuesta correcta' y la respuesta aceptada. Una respuesta aceptada es solo la respuesta que fue útil para quien hizo la pregunta.
Steven
44
Supongo que puede haber problemas con la plataforma Windows porque puede haber barras diagonales. Por lo tanto, la expresión regular debe ser /\.[^/\\.font>+$/.
Alex Chuev
1
@ElgsQianChen aquí hay una gran herramienta para ayudarlo a responder su pregunta regexr.com
John Hartsock
281

En node.js , el nombre del archivo sin la extensión se puede obtener de la siguiente manera.

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

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

Explicación adicional en la página de documentación de Node.js.

Jibesh Patra
fuente
2
De qué está hablando @kaasdude ... este método elimina efectivamente la extensión en el nodo. No estoy seguro de lo que quería expresar, pero este método funciona con perlas.
Erick
1
Esta respuesta está bastante restringida al nodo del lado del servidor. Si intenta usar esto en el código de reacción, no parece importar.
Charlie
1
si desea eliminar una extensión de una ruta que incluye los directorios, puede hacerlo var parsed = path.parse(filename)seguido de path.join(parsed.dir, parsed.name).
Jespertheend
Otra posibilidad es let base = path.basename( file_path, path.extname( file_path ) ).
bicarlsen
116

x.length-4solo representa extensiones de 3 caracteres. ¿Qué pasa si tienes filename.jpego filename.pl?

EDITAR:

Para responder ... seguro, si siempre tiene una extensión de .jpg, x.length-4funcionaría bien.

Sin embargo, si no conoce la longitud de su extensión, cualquiera de varias soluciones es mejor / más sólida.

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

O

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

O

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

O (con el supuesto nombre de archivo solo tiene un punto)

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

O (también con un solo punto)

parts = x.split(".");
x = parts[0];
Jeff B
fuente
12
?? Puede tener un nombre de archivo ej: "summer.family.jpg" en ese caso, split ('.') [0] devolverá solo un nombre de archivo parcial. Quitaría esa de la respuesta, o declararía claramente debajo del problema para ese ejemplo. @basarat ...
Roko C. Buljan
Algo que hago con frecuencia con respecto a las divisiones var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join(".");
parciales
x.split (".") ni siquiera debería considerarse una respuesta. Sé que uso un '.' en casi todas mis convenciones de nomenclatura de archivos, es decir, 'survey.controller.js' o 'my.family.jpg'.
Lee Brindley
@ Lee2808: De ahí la advertencia de un solo punto. Esto simplemente pretende mostrar que hay una serie de enfoques, dependiendo de la aplicación. Ciertamente usaría uno de los otros métodos en casi todos los casos.
Jeff B
x = x.substr(0, x.lastIndexOf('.'));- Probablemente quisiste decir x = x.substring(0, x.lastIndexOf('.'));?
Dziad Borowy
39

Quizás pueda usar la suposición de que el último punto será el delimitador de extensión.

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

Si el archivo no tiene extensión, devolverá una cadena vacía. Para arreglar eso use esta función

function removeExtension(filename){
    var lastDotPosition = filename.lastIndexOf(".");
    if (lastDotPosition === -1) return filename;
    else return filename.substr(0, lastDotPosition);
}
Martin Algesten
fuente
Advertencia, esto falla si no hay una extensión de nombre de archivo. Te quedan con una cuerda vacía.
Brad
18
Versión más corta que no tiene puntos. var f = x.substr(0, x.lastIndexOf('.')) || x;Esto funciona porque una cadena vacía es falsa, por lo tanto, devuelve x.
Jonathan Rowny
22

Me gusta este porque es un trazador de líneas que no es demasiado difícil de leer:

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

En las versiones de Node.js anteriores a 0.12.x:

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

Por supuesto, esto también funciona en 0.12.xy posteriores.

blah238
fuente
La path.parserespuesta es más simple.
Dan Dascalescu
12

Esto funciona, incluso cuando el delimitador no está presente en la cadena.

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"

También se puede usar como una línea como esta:

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

EDITAR: Esta es una solución más eficiente:

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

No sé si es una opción válida, pero uso esto:

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.

No solo conozco una operación, sino que al menos siempre debería funcionar.

ACTUALIZACIÓN: Si quieres un oneliner, aquí estás:

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

Giacomo Cerquone
fuente
1
No debe ser name.join ('') sino name.join ('.'). Se divide por punto pero se une por coma, así que hello.name.txtregresahello, name
Evil
7

Otra frase:

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

Aquí hay otra solución basada en expresiones regulares:

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

Esto solo debería cortar el último segmento.

Chad Johnson
fuente
7

Uno simple:

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

La respuesta aceptada elimina solo la última parte de la extensión ( .jpeg), que podría ser una buena opción en la mayoría de los casos.

Una vez tuve que quitar todas las extensiones ( .tar.gz) y los nombres de los archivos estaban restringidos para no contener puntos (por 2015-01-01.backup.tarlo que no sería un problema):

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");
básico6
fuente
4
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"
Yas
fuente
Este es el único método hasta ahora que funciona para rutas completas: path/name.ext-> en paht/namelugar de solo regresar name, pero preferiría hacerlo con, fs.parseaunque es un poco más detallado: stackoverflow.com/a/59576950/895245
Ciro Santilli 郝海东 冠状 病六四 事件 法轮功
3

Si tiene que procesar una variable que contiene la ruta completa (ej .:) thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg"y desea devolver solo "nombre de archivo", puede usar:

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

el resultado será theName == "filename" ;

Para probarlo escriba el siguiente comando en la ventana de la consola de su depurador de Chrome window.location.pathname.split("/").slice(-1).join().split(".").shift()

Si tiene que procesar solo el nombre del archivo y su extensión (ej .:) theNameWithExt = "filename.jpg":

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

el resultado será theName == "filename" , el mismo que el anterior;

Notas:

  1. El primero es un poco más lento porque realiza más operaciones; pero funciona en ambos casos, en otras palabras, puede extraer el nombre del archivo sin extensión de una cadena dada que contiene una ruta o un nombre de archivo con ex. Mientras que el segundo funciona solo si la variable dada contiene un nombre de archivo con ext como filename.ext pero es un poco más rápido.
  2. Ambas soluciones funcionan para archivos locales y de servidor;

Pero no puedo decir nada sobre la comparación de rendimiento con otras respuestas ni sobre la compatibilidad del navegador o el sistema operativo.

fragmento de trabajo 1: la ruta completa

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

fragmento de trabajo 2: el nombre del archivo con extensión

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

fragmento de trabajo 2: el nombre del archivo con doble extensión

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

Willy Wonka
fuente
3

Aunque es bastante tarde, agregaré otro enfoque para obtener el nombre de archivo sin extensión usando JS-

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

Munim Dibosh
fuente
o path.split('.').pop()para extensiones de archivo de una parte
mixdev
¡En realidad estaba tratando de obtener el nombre del archivo, no la extensión!
Munim Dibosh el
3

Node.js elimina la extensión del directorio completo de mantenimiento de rutas

https://stackoverflow.com/a/31615711/895245 por ejemplo did path/hello.html-> hello, pero si quieres path/hello.html-> path/hello, puedes usar esto:

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

directorio de salidas también:

path/hello

https://stackoverflow.com/a/36099196/895245 también logra esto, pero este enfoque me parece un poco más semántico.

Probado en Node.js v10.15.2.

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

¡Aquí es donde las expresiones regulares son útiles! El .replace()método de Javascript tomará una expresión regular, y puede utilizarlo para lograr lo que desea:

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

Otro revestimiento: suponemos que nuestro archivo es una imagen jpg >> ex: var yourStr = 'test.jpg';

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

Puedes usar pathpara maniobrar.

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

Salida

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

Este es el código que uso para eliminar la extensión de un nombre de archivo, sin usar regex o indexOf (indexOf no es compatible con IE8). Se supone que la extensión es cualquier texto después del último '.' personaje.

Funciona para:

  • archivos sin extensión: "myletter"
  • archivos con '.' en el nombre: "my.letter.txt"
  • longitud desconocida de la extensión de archivo: "my.letter.html"

Aquí está el código:

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;
}
Pequeño cerebro
fuente
falla con hello.tar.gz, la salida es hellotar.
Asif Ali
#AsifAli gracias, tienes razón, olvidé leer la extensión del archivo. He actualizado la respuesta, espero que funcione ahora.
Little Brain
-3

Usaría algo como x.substring (0, x.lastIndexOf ('.')). Si va por el rendimiento, no use javascript en absoluto :-p No, una declaración más realmente no importa para el 99.99999% de todos los propósitos.

Lucas Moeskops
fuente
2
"Si buscas rendimiento, no busques javascript en absoluto" - ¿Qué más sugieres usar en las aplicaciones web ...?
TJ
No menciona las aplicaciones web.
Lucas Moeskops
1
Esta pregunta se hizo y la respuesta se publicó en 2010, hace 7 años, y JavaScript se usó prácticamente solo en aplicaciones web. (Node acaba de nacer, ni siquiera tenía una guía o NPM en ese momento)
TJ
;-) Aún así, si el rendimiento es importante en tareas como esta, puede considerar hacer esto en el backend y procesar los resultados en la interfaz.
Lucas Moeskops el