Jak przyciąć rozszerzenie pliku z ciągu w JavaScript?

295

Na przykład, zakładając x = filename.jpg, że chcę uzyskać filename, gdzie filenamemoże być dowolna nazwa pliku (załóżmy, że nazwa pliku zawiera tylko [a-zA-Z0-9-_] w celu uproszczenia.).

Widziałem x.substring(0, x.indexOf('.jpg'))na fragmentach DZone , ale czy nie działałby x.substring(0, x.length-4)lepiej? Ponieważ lengthjest właściwością i nie sprawdza znaków, podczas gdy indexOf()jest funkcją i sprawdza znaki.

ma11hew28
źródło
Niemal tak samo jak stackoverflow.com/questions/1991608/... . I chyba, że ​​wykonasz jedną z wielu takich czynności, martwisz się o wydajność, jest to Optymalizacja przedwczesna.
Archetypal Paul
W wieku ES6 zobacz także moduł Ścieżka - na wypadek, gdy używasz nodejs lub właściwej transpilacji
Frank Nocke,

Odpowiedzi:

173

Jeśli znasz długość rozszerzenia, możesz użyć x.slice(0, -4)(gdzie 4 to trzy znaki rozszerzenia i kropka).

Jeśli nie znasz długości, wyrażenie regularne @John Hartsock byłoby właściwym podejściem.

Jeśli wolisz nie używać wyrażeń regularnych, możesz wypróbować to (mniej wydajne):

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

Pamiętaj, że nie powiedzie się na plikach bez rozszerzenia.

Marek Sapota
źródło
Najbardziej podoba mi się to rozwiązanie. Jest czysty i mogę go używać, ponieważ wiem, że rozszerzenie pliku jest zawsze .jpg. Szukałem czegoś takiego jak Ruby x[0..-5]i x.slice(0, -4)wygląda świetnie! Dzięki! I dziękuję wszystkim innym za wszystkie inne solidne alternatywy!
ma11hew28,
22
nie jest to optymalne rozwiązanie, sprawdź inne rozwiązania poniżej.
bunjeeb,
8
A jeśli nie masz 100% pewności co do długości rozszerzenia, nie rób tego: "picture.jpeg".slice(0, -4)-> „picture”.
basic6
13
To niebezpieczne rozwiązanie, ponieważ tak naprawdę nie znasz długości formatu.
Koder
„Jeśli znasz długość przedłużenia” Minęły dziesięciolecia, ponieważ było to możliwe do przyjęcia założenie. Nie używaj tego więcej.
Alexander - Przywróć Monikę
453

Nie jestem pewien, co by działało szybciej, ale byłoby to bardziej niezawodne, jeśli chodzi o rozszerzenie, takie jak .jpeglub.html

x.replace(/\.[^/.]+$/, "")
John Hartsock
źródło
15
Prawdopodobnie chcesz również wyłączyć / jako separator ścieżek, więc wyrażenie regularne to /\.[^/.]+$/
gsnedders
Działa to dla dowolnej długości rozszerzenia pliku (.txt lub .html lub .htaccess), a także pozwala, aby nazwa pliku zawierała dodatkowe znaki kropki (.). Nie poradziłby sobie np. .Tar.gz, ponieważ samo rozszerzenie zawiera kropkę. Częściej zdarza się, że nazwa pliku zawiera dodatkowe kropki niż rozszerzenie pliku. Dzięki!
Steve Seeger
2
@Vik Istnieje różnica między „właściwą odpowiedzią” a odpowiedzią zaakceptowaną. Akceptowana odpowiedź to tylko odpowiedź, która była pomocna dla tego, kto zadał pytanie.
Steven
4
Przypuszczam, że mogą występować problemy z platformą Windows, ponieważ mogą występować ukośniki. Zatem regexp powinien być /\.[^/\\.]+$/.
Alex Chuev,
1
@ElgsQianChen tutaj jest doskonałym narzędziem, które pomoże Ci odpowiedzieć na twoje pytanie regexr.com
John Hartsock
281

W node.js nazwę pliku bez rozszerzenia można uzyskać w następujący sposób.

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

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

Dalsze objaśnienia na stronie dokumentacji Node.js.

Jibesh Patra
źródło
2
O czym mówisz @kaasdude .... ta metoda skutecznie usuwa rozszerzenie w węźle. Nie jestem pewien, co chciałbyś wyrazić, ale ta metoda działa na perły.
Erick
1
Ta odpowiedź jest dość ograniczona do węzła po stronie serwera. Jeśli spróbujesz użyć tego w kodzie reagującym, wydaje się, że nie jest importowany.
Charlie,
1
jeśli chcesz usunąć rozszerzenie ze ścieżki zawierającej katalogi, możesz zrobić to var parsed = path.parse(filename)po path.join(parsed.dir, parsed.name).
Jespertheend
Inną możliwością jest let base = path.basename( file_path, path.extname( file_path ) ).
bicarlsen
116

x.length-4uwzględnia tylko rozszerzenia 3 znaków. Co jeśli masz filename.jpeglub filename.pl?

EDYTOWAĆ:

Aby odpowiedzieć ... na pewno, jeśli zawsze masz rozszerzenie .jpg, x.length-4działałoby dobrze.

Jeśli jednak nie znasz długości swojego rozszerzenia, dowolne z wielu rozwiązań jest lepsze / bardziej niezawodne.

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

LUB

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

LUB

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

LUB (przy założeniu, że nazwa pliku ma tylko jedną kropkę)

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

LUB (także z tylko jedną kropką)

parts = x.split(".");
x = parts[0];
Jeff B.
źródło
12
?? Możesz mieć nazwę pliku np .: „summer.family.jpg” w takim przypadku split ('.') [0] zwróci tylko częściową nazwę pliku. Chciałbym usunąć ten z odpowiedzi lub wyraźnie wskazać problem pod tym przykładem. @basarat ...
Roko C. Buljan
Coś, co często robię, jeśli chodzi o podział części:var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join(".");
radicand
x.split („.”) nie powinno być nawet uważane za odpowiedź. Wiem, że używam „.” w prawie wszystkich moich konwencjach nazewnictwa plików, tj. „survey.controller.js” lub „my.family.jpg”.
Lee Brindley,
@ Lee2808: Stąd ostrzeżenie o jednej kropce. Ma to po prostu pokazać, że istnieje wiele podejść, w zależności od zastosowania. Z pewnością zastosowałbym jedną z pozostałych metod w prawie wszystkich przypadkach.
Jeff B
x = x.substr(0, x.lastIndexOf('.'));- prawdopodobnie miałeś na myśli x = x.substring(0, x.lastIndexOf('.'));?
Dziad Borowy
39

Być może możesz przyjąć założenie, że ostatnia kropka będzie ogranicznikiem rozszerzenia.

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

Jeśli plik nie ma rozszerzenia, zwróci pusty ciąg. Aby to naprawić, użyj tej funkcji

function removeExtension(filename){
    var lastDotPosition = filename.lastIndexOf(".");
    if (lastDotPosition === -1) return filename;
    else return filename.substr(0, lastDotPosition);
}
Martin Algesten
źródło
Ostrzeżenie: nie powiedzie się, jeśli nie będzie rozszerzenia pliku. Pozostaje ci pusty łańcuch.
Brad
18
Krótsza wersja, która nie zawiera kropek. var f = x.substr(0, x.lastIndexOf('.')) || x;Działa to, ponieważ pusty ciąg znaków jest fałszem, dlatego zwraca x.
Jonathan Rowny,
22

Podoba mi się ten, ponieważ jest to jeden liniowiec, który nie jest zbyt trudny do odczytania:

filename.substring(0, filename.lastIndexOf('.')) || filename
jakubiszon
źródło
17

W wersjach Node.js wcześniejszych niż 0.12.x:

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

Oczywiście działa to również w wersji 0.12.xi późniejszych.

blah238
źródło
path.parseOdpowiedź jest prostsza.
Dan Dascalescu
12

Działa to nawet wtedy, gdy ogranicznik nie występuje w ciągu.

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"

Może być również użyty jako jedna linijka:

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

EDYCJA: To jest bardziej wydajne rozwiązanie:

String.prototype.beforeLastIndex = function (delimiter) {
    return this.substr(0,this.lastIndexOf(delimiter)) || this + ""
}
Andrew Plank
źródło
10

Nie wiem, czy jest to prawidłowa opcja, ale używam tego:

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.

Wiem, że to nie tylko jedna operacja, ale przynajmniej powinna zawsze działać!

AKTUALIZACJA: Jeśli chcesz oneliner, oto jesteś:

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

Giacomo Cerquone
źródło
1
Nie powinien to być name.join (''), ale name.join ('.'). Dzielisz przez kropkę, ale dołączasz przecinkiem, więc hello.name.txtwracahello, name
Zły
7

Kolejna linijka:

x.split(".").slice(0, -1).join(".")
Jacob Bundgaard
źródło
7

Oto inne rozwiązanie oparte na wyrażeniach regularnych:

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

To powinno odciąć tylko ostatni segment.

Chad Johnson
źródło
7

Prosty:

var n = str.lastIndexOf(".");
return n > -1 ? str.substr(0, n) : str;
Dugh
źródło
6

Zaakceptowana odpowiedź usuwa tylko ostatnią część rozszerzenia ( .jpeg), co może być dobrym wyborem w większości przypadków.

Kiedyś musiałem usunąć wszystkie rozszerzenia ( .tar.gz), a nazwy plików były ograniczone, aby nie zawierały kropek (więc 2015-01-01.backup.tarnie byłoby problemu):

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");
podstawowy 6
źródło
4
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"
Tak
źródło
Jest to jedyna jak dotąd metoda, która działa dla pełnych ścieżek: path/name.ext-> paht/namezamiast po prostu wracać name, ale wolałabym zrobić z, fs.parsechoć jest to nieco bardziej szczegółowe: stackoverflow.com/a/59576950/895245
Ciro Santilli 郝海东 冠状 病法轮功 事件 法轮功
3

Jeśli musisz przetworzyć zmienną zawierającą pełną ścieżkę (np .:) thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg"i chcesz zwrócić tylko „nazwę pliku”, możesz użyć:

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

wynikiem będzie nazwa == "nazwa pliku" ;

Aby spróbować, wpisz następującą komendę w oknie konsoli debuggera chrome: window.location.pathname.split("/").slice(-1).join().split(".").shift()

Jeśli musisz przetworzyć tylko nazwę pliku i jego rozszerzenie (np .:) theNameWithExt = "filename.jpg":

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

wynikiem będzie nazwa == „nazwa pliku” , taka sama jak powyżej;

Uwagi:

  1. Pierwszy jest nieco wolniejszy, ponieważ wykonuje więcej operacji; ale działa w obu przypadkach, innymi słowy, może wyodrębnić nazwę pliku bez rozszerzenia z danego ciągu zawierającego ścieżkę lub nazwę pliku np. Podczas gdy drugi działa tylko wtedy, gdy dana zmienna zawiera nazwę pliku z rozszerzeniem jak filename.ext, ale jest nieco szybsza.
  2. Oba rozwiązania działają zarówno z plikami lokalnymi, jak i serwerowymi;

Ale nie mogę powiedzieć nic o porównaniu wydajności z innymi odpowiedziami ani o zgodności przeglądarki lub systemu operacyjnego.

fragment roboczy 1: pełna ścieżka

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

fragment roboczy 2: nazwa pliku z rozszerzeniem

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

fragment roboczy 2: nazwa pliku z podwójnym rozszerzeniem

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

Willy Wonka
źródło
3

Chociaż jest dość późno, dodam inne podejście do uzyskania nazwy pliku bez rozszerzenia przy użyciu zwykłego starego JS-

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

Munim Dibosh
źródło
lub path.split('.').pop()dla rozszerzeń plików z jedną częścią
mixdev
W rzeczywistości próbował zdobyć nazwę pliku, a nie rozszerzenie!
Munim Dibosh,
3

Node.js usuwa rozszerzenie z katalogu prowadzącego pełną ścieżkę

https://stackoverflow.com/a/31615711/895245 na przykład zrobił path/hello.html-> hello, ale jeśli chcesz path/hello.html-> path/hello, możesz użyć tego:

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

wypisuje również katalog:

path/hello

https://stackoverflow.com/a/36099196/895245 również to osiąga, ale uważam, że to podejście jest nieco bardziej semantycznie przyjemne.

Testowane w Node.js 10.15.2.

Ciro Santilli
źródło
0

Tutaj przydają się wyrażenia regularne! .replace()Metoda Javascript przyjmuje wyrażenie regularne i możesz go wykorzystać do osiągnięcia tego, co chcesz:

// assuming var x = filename.jpg or some extension
x = x.replace(/(.*)\.[^.]+$/, "$1");
Alex
źródło
0

Kolejna linijka - zakładamy, że naszym plikiem jest obraz jpg >> np .: var yourStr = 'test.jpg';

    yourStr = yourStr.slice(0, -4); // 'test'
Sorin N.
źródło
0

Możesz użyć pathdo manewru.

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

Wynik

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

To jest kod, którego używam do usunięcia rozszerzenia z nazwy pliku, bez użycia wyrażenia regularnego lub indexOf (indexOf nie jest obsługiwany w IE8). Zakłada się, że rozszerzeniem jest dowolny tekst po ostatnim „.” postać.

Działa dla:

  • pliki bez rozszerzenia: „myletter”
  • pliki z „.” w nazwie: „my.letter.txt”
  • nieznana długość rozszerzenia pliku: „my.letter.html”

Oto kod:

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;
}
Mały mózg
źródło
kończy się niepowodzeniem hello.tar.gz, wynikiem jest hellotar.
Asif Ali,
#AsifAli dzięki, masz rację, zapomniałem przeczytać rozszerzenie pliku. Zaktualizowałem odpowiedź, mam nadzieję, że teraz działa.
Little Brain
-3

Chciałbym użyć czegoś takiego jak x.substring (0, x.lastIndexOf ('.')). Jeśli szukasz wydajności, nie używaj javascript :-p Nie, jeszcze jedno zdanie naprawdę nie ma znaczenia dla 99,99999% wszystkich celów.

Lucas Moeskops
źródło
2
„Jeśli zależy Ci na wydajności, nie wybieraj javascript” - czego jeszcze sugerujesz używać w aplikacjach internetowych…?
TJ
Nie wspomina o aplikacjach internetowych.
Lucas Moeskops
1
To pytanie zostało zadane, a odpowiedź została opublikowana w 2010 roku, 7 lat temu, a JavaScript był używany głównie w aplikacjach internetowych. (Węzeł właśnie się urodził, nie miał nawet przewodnika ani NPM w tym czasie)
TJ
;-) Mimo to, jeśli wydajność ma znaczenie w takich zadaniach, możesz rozważyć wykonanie tego na backendie i przetworzenie wyników na frontendie.
Lucas Moeskops