Como cortar uma extensão de arquivo de uma String em JavaScript?


295

Por exemplo, supondo que x = filename.jpg, eu quero obter filename, onde filenamepoderia haver qualquer nome de arquivo (suponha que o nome do arquivo contenha apenas [a-zA-Z0-9-_] para simplificar).

Vi x.substring(0, x.indexOf('.jpg'))no DZone Snippets , mas não teria um x.substring(0, x.length-4)desempenho melhor? Porque, lengthé uma propriedade e não realiza a verificação de caracteres, enquanto indexOf()é uma função e realiza a verificação de caracteres.



Praticamente o mesmo que stackoverflow.com/questions/1991608/… . E, a menos que você faça muitas dessas, a preocupação com a eficiência é a Otimização prematura.
— The Archetypal Paul

Na era da ES6, veja também o Caminho do módulo - no caso de você estiver usando nodejs ou um transpilation adequada
— Frank Nocke

Respostas:


173

Se você souber o comprimento da extensão, poderá usar x.slice(0, -4)(onde 4 são os três caracteres da extensão e o ponto).

Se você não souber o comprimento, a regex @John Hartsock seria a abordagem certa.

Se você preferir não usar expressões regulares, tente isso (menos desempenho):

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

Observe que ele falhará nos arquivos sem extensão.


Eu gosto desta solução da melhor maneira. É limpo e posso usá-lo porque sei que a extensão do arquivo é sempre .jpg. Eu estava procurando por algo como o Ruby x[0..-5], e x.slice(0, -4)está ótimo! Obrigado! E obrigado a todos por todas as outras alternativas robustas fornecidas!
— ma11hew28

22
Esta não é a solução ideal, verifique outras soluções abaixo.
— bunjeeb

8
E se você não tiver 100% de certeza sobre o comprimento da extensão, não faça o seguinte: "picture.jpeg".slice(0, -4)-> "imagem".
— usar o seguinte

13
Esta é uma solução perigosa, porque você realmente não sabe o tamanho do formato.
— Coder

"Se você sabe o tamanho da extensão" Já faz décadas desde que essa era uma suposição aceitável a ser feita. Não use mais isso.
— Alexander - Restabelecer Monica

453

Não tenho certeza do que teria um desempenho mais rápido, mas isso seria mais confiável quando se trata de extensões como .jpegou.html

x.replace(/\.[^/.]+$/, "")

15
Você provavelmente também deseja proibir / como um separador de caminho, portanto, o regexp é /\.[^/.orgeous
— $/

Isso funciona para qualquer extensão de arquivo (.txt ou .html ou .htaccess) e também permite que o nome do arquivo contenha caracteres adicionais de ponto (.). Não suportaria, por exemplo, .tar.gz devido à extensão em si que contém um período. É mais comum que um nome de arquivo contenha períodos adicionais que uma extensão de arquivo. Obrigado!
— Steve Seeger

2
@ Vik Há uma diferença entre a 'resposta certa' e a resposta aceita. Uma resposta aceita é apenas a resposta que foi útil para quem fez a pergunta.
— Steven

4
Suponho que possa haver problemas com a plataforma Windows, pois pode haver barras invertidas. Portanto, o regexp deve ser /\.[^/\\.ξ+$/.
— Alex Chuev

1
@ElgsQianChen aqui é uma ótima ferramenta para você responder ajuda sua pergunta regexr.com
— John Hartsock

281

No node.js , o nome do arquivo sem a extensão pode ser obtido da seguinte maneira.

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

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

Mais explicações na página de documentação do Node.js.


2
Sobre o que você está falando @kaasdude .... esse método remove efetivamente a extensão no nó., Não sabe o que você queria expressar, mas esse método funciona como pérolas.
— Erick

1
Esta resposta é bastante restrita ao nó do lado do servidor. Se você tentar usar isso no código de reação, ele não parece importar.
— 077 Charlie

1
se você deseja remover uma extensão de um caminho, incluindo os diretórios, var parsed = path.parse(filename)siga-o path.join(parsed.dir, parsed.name).
— Jespertheend

Outra possibilidade é let base = path.basename( file_path, path.extname( file_path ) ).
— bicarlsen 12/03

116

x.length-4representa apenas extensões de 3 caracteres. E se você tiver filename.jpegou filename.pl?

EDITAR:

Para responder ... claro, se você sempre tiver uma extensão de .jpg, x.length-4funcionaria muito bem.

No entanto, se você não souber o tamanho da sua extensão, qualquer uma de várias soluções será melhor / mais robusta.

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

OU

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

OU

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

OU (com o nome do arquivo suposto apenas com um ponto)

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

OU (também com apenas um ponto)

parts = x.split(".");
x = parts[0];

12
?? Você pode ter um nome de arquivo ex: "summer.family.jpg" nesse caso, split ('.') [0] retornará apenas um nome de arquivo parcial. Eu o removeria da resposta ou declararia claramente a questão desse exemplo. @basarat ...
— Roko C. Buljan

Algo que eu freqüentemente sobre splits da peça:var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join(".");
— radicando

x.split (".") nem deve ser considerado uma resposta. Eu sei que uso um '.' em quase todas as convenções de nomenclatura de arquivos, como 'survey.controller.js' ou 'my.family.jpg'.
— 21816 Lee Brindley

@ Lee2808: Daí o aviso de apenas um ponto. Isso significa simplesmente mostrar que existem várias abordagens, dependendo do aplicativo. Eu certamente usaria um dos outros métodos em quase todos os casos.
— Jeff B

x = x.substr(0, x.lastIndexOf('.'));- você provavelmente quis dizer x = x.substring(0, x.lastIndexOf('.'));?
— Dziad Borowy

39

Talvez você possa usar a suposição de que o último ponto será o delimitador de extensão.

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

Se o arquivo não tiver extensão, ele retornará uma string vazia. Para corrigir isso, use esta função

function removeExtension(filename){
    var lastDotPosition = filename.lastIndexOf(".");
    if (lastDotPosition === -1) return filename;
    else return filename.substr(0, lastDotPosition);
}

Aviso, isso falhará se não houver extensão de nome de arquivo. Você fica com uma corda vazia.
— Brad

18
Versão mais curta que representa nenhum ponto. var f = x.substr(0, x.lastIndexOf('.')) || x;Isso funciona porque uma string vazia é falsa e, portanto, retorna x.
— Jonathan Rowny

22

Eu gosto deste porque é um liner que não é muito difícil de ler:

filename.substring(0, filename.lastIndexOf('.')) || filename


12

Isso funciona, mesmo quando o delimitador não está presente na 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"

Também pode ser usado como uma linha como esta:

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

EDIT: Esta é uma solução mais eficiente:

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

10

Não sei se é uma opção válida, mas uso isso:

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.

Não é apenas uma operação que eu conheço, mas pelo menos deve sempre funcionar!

ATUALIZAÇÃO: Se você deseja um oneliner, aqui está:

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


1
Não deve ser name.join (''), mas name.join ('.'). Você dividir por ponto, mas se juntar por vírgula, assim hello.name.txtretornoshello, name
— Mal


7

Aqui está outra solução baseada em regex:

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

Isso deve cortar apenas o último segmento.


7

Simples:

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

6

A resposta aceita retira apenas a última parte da extensão ( .jpeg), que pode ser uma boa escolha na maioria dos casos.

Uma vez tive que remover todas as extensões ( .tar.gz) e os nomes dos arquivos foram restritos para não conter pontos (por 2015-01-01.backup.tarisso não seria um problema):

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");


3

Se você precisar processar uma variável que contenha o caminho completo (ex .:) thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg"e desejar retornar apenas "nome do arquivo", poderá usar:

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

o resultado será theName == "filename" ;

Para tentar, escreva o seguinte comando na janela do console do seu depurador chrome: window.location.pathname.split("/").slice(-1).join().split(".").shift()

Se você precisar processar apenas o nome do arquivo e sua extensão (ex .:) theNameWithExt = "filename.jpg":

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

o resultado será theName == "filename" , o mesmo que acima;

Notas:

  1. O primeiro é um pouco mais lento, porque realiza mais operações; mas funciona nos dois casos, ou seja, pode extrair o nome do arquivo sem extensão de uma determinada sequência que contém um caminho ou um nome de arquivo com ex. Enquanto o segundo funciona apenas se a variável especificada contém um nome de arquivo com ext como filename.ext, mas é um pouco mais rápido.
  2. Ambas as soluções funcionam para arquivos locais e do servidor;

Mas não posso dizer nada sobre a comparação de desempenhos com outras respostas, nem sobre a compatibilidade do navegador ou do SO.

trecho de trabalho 1: o caminho completo

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

trecho de trabalho 2: o nome do arquivo com extensão

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

trecho de trabalho 2: o nome do arquivo com extensão dupla

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


3

Embora seja muito tarde, adicionarei outra abordagem para obter o nome do arquivo sem extensão, usando JS-

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


ou path.split('.').pop()para extensões de arquivo de uma parte
— mixdev 5/09/19

Ele estava realmente tentando obter o nome do arquivo, não a extensão!
— Munim Dibosh 12/09/19

3

O Node.js remove a extensão do diretório de manutenção de caminho completo

https://stackoverflow.com/a/31615711/895245, por exemplo, fez path/hello.html-> hello, mas se você quiser path/hello.html-> path/hello, pode usar isso:

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

diretório de saídas também:

path/hello

https://stackoverflow.com/a/36099196/895245 também consegue isso, mas acho essa abordagem um pouco mais semanticamente agradável.

Testado no Node.js v10.15.2.


0

É aqui que as expressões regulares são úteis! O .replace()método do Javascript terá uma expressão regular, e você pode utilizá-lo para realizar o que deseja:

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

0

Outro liner - presumimos que nosso arquivo seja uma imagem jpg >> ex: var yourStr = 'test.jpg';

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

0

Você pode usar pathpara manobrar.

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

Resultado

> filePath
'/User/HELLO/WORLD/FILENAME'
> fileName
'FILENAME'
> MYPATH
'/User/HELLO/WORLD/FILENAME.js'


0

Este é o código que eu uso para remover a extensão de um nome de arquivo, sem usar regex ou indexOf (indexOf não é suportado no IE8). Pressupõe que a extensão seja qualquer texto após o último '.' personagem.

Funciona para:

  • arquivos sem extensão: "myletter"
  • arquivos com '.' no nome: "my.letter.txt"
  • comprimento desconhecido da extensão do arquivo: "my.letter.html"

Aqui está o 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;
}

falha com hello.tar.gz, a saída é hellotar.
— Asif Ali #

#AsifAli obrigado, você está certo, esqueci de ler a extensão do arquivo. Atualizei a resposta, espero que funcione agora.
— Little Brain

-3

Eu usaria algo como x.substring (0, x.lastIndexOf ('.')). Se você deseja desempenho, não use javascript :-p Não, mais uma declaração realmente não importa para 99,99999% de todos os propósitos.


2
"Se você quer desempenho, não use javascript" - O que mais você está sugerindo para usar em aplicativos da web ...?
— TJ

Ele não menciona aplicativos da web.
— Lucas Moeskops 22/03

1
Esta pergunta foi feita e a resposta foi postada em 2010, há 7 anos, e o JavaScript era praticamente usado apenas em aplicativos da web. (Node acabou de nascer, ele nem sequer tinha um guia ou NPM na época)
— TJ

;-) Ainda assim, se o desempenho é importante em tarefas como essa, você pode fazer isso no back-end e processar os resultados no front-end.
— Lucas Moeskops
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.