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.

ma11hew28
fonte
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.

Marek Sapota
fonte
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(/\.[^/.]+$/, "")
John Hartsock
fonte
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.

Jibesh Patra
fonte
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];
Jeff B
fonte
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);
}
Martin Algesten
fonte
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
jakubiszon
fonte
17

Nas versões do Node.js anteriores à 0.12.x:

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

Obviamente, isso também funciona em 0.12.xe posterior.

blah238
fonte
A path.parseresposta é mais simples.
Dan Dascalescu 17/03
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 + ""
}
Andrew Plank
fonte
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('.')

Giacomo Cerquone
fonte
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

Outra linha:

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

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

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

Isso deve cortar apenas o último segmento.

Chad Johnson
fonte
7

Simples:

var n = str.lastIndexOf(".");
return n > -1 ? str.substr(0, n) : str;
Dugh
fonte
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(/(\.[^/.]+)+$/, "");
basic6
fonte
4
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"
Yas
fonte
Até agora, este é o único método que funciona para caminhos completos: path/name.ext-> em paht/namevez de retornar name, mas eu prefiro continuar com, fs.parseembora seja um pouco mais detalhado: stackoverflow.com/a/59576950/895245
Ciro Santilli 郝海东 冠状 病3 事件 法轮功 03/01
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);
  

Willy Wonka
fonte
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('.')), '')

Munim Dibosh
fonte
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.

Ciro Santilli adicionou uma nova foto
fonte
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");
Alex
fonte
0

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

    yourStr = yourStr.slice(0, -4); // 'test'
SorinN
fonte
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'
Alan Dong
fonte
0
x.slice(0, -(x.split('.').pop().length + 1));
ishandutta2007
fonte
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;
}
Little Brain
fonte
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.

Lucas Moeskops
fonte
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