Как обрезать расширение файла из строки в JavaScript?


295

Например, предполагая, что x = filename.jpgя хочу получить filename, где filenameможет быть любое имя файла (предположим, что имя файла содержит только [a-zA-Z0-9-_] для упрощения.).

Я видел x.substring(0, x.indexOf('.jpg'))на DZone Snippets , но не будет ли x.substring(0, x.length-4)лучше? Потому lengthчто это свойство и не выполняет проверку символов, тогда как indexOf()является функцией и проверкой символов.



Почти так же, как stackoverflow.com/questions/1991608/… . И если вы не сделаете один из них, беспокойство по поводу эффективности будет преждевременной оптимизацией.
— Архетип Павла

В эпоху ES6 см. Также модуль Path - в случае, если вы используете nodejs или правильную транспиляцию
— Frank

Ответы:


173

Если вы знаете длину расширения, вы можете использовать его x.slice(0, -4)(где 4 - это три символа расширения и точка).

Если вы не знаете длину, регулярное выражение @John Hartsock будет правильным подходом.

Если вы не хотите использовать регулярные выражения, вы можете попробовать это (менее производительно):

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

Обратите внимание, что это не удастся для файлов без расширения.


Мне нравится это решение больше всего. Это чисто, и я могу использовать его, потому что я знаю, что расширение файла всегда .jpg. Я искал что-то вроде Ruby's x[0..-5]и x.slice(0, -4)отлично выглядит! Спасибо! И спасибо всем остальным за все другие надежные альтернативы!
— ma11hew28

22
это не оптимальное решение, пожалуйста, проверьте другие решения ниже.
— bunjeeb

8
И если вы не уверены на 100% в длине расширения, то не делайте этого: "picture.jpeg".slice(0, -4)-> «картинка».
— basic6

13
Это опасное решение, потому что вы не знаете длину формата.
— Кодер

«Если вы знаете длину расширения» Прошли десятилетия, так как это было приемлемое предположение. Не используйте это больше.
— Александр - Восстановить Монику

454

Не уверен, что будет работать быстрее, но это будет более надежно, когда речь идет о расширении, как .jpegили.html

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

15
Вы, вероятно, хотите также запретить / в качестве разделителя пути, поэтому регулярное выражение будет /\.[^/.]+$/
— gsnedders

Это работает для любого расширения файла (.txt или .html или .htaccess), а также позволяет имени файла содержать дополнительные символы точки (.). Он не будет обрабатывать, например .tar.gz из-за самого расширения, содержащего точку. Обычно имя файла содержит дополнительные точки, а не расширение файла. Спасибо!
— Стив Сигер

2
@ Вик Есть разница между «правильным ответом» и принятым ответом. Принятый ответ - это просто ответ, который был полезен для того, кто задал вопрос.
— Стивен

4
Я предполагаю, что могут быть проблемы с платформой Windows, потому что могут быть обратные косые черты. Поэтому регулярное выражение должно быть /\.[^/\\.]+$/.
— Алексей Чуев

1
@ElgsQianChen вот отличный инструмент, чтобы помочь вам ответить на ваш вопрос regexr.com
— Джон Хартсок

281

В файле node.js имя файла без расширения можно получить следующим образом.

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

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

Дальнейшее объяснение на странице документации Node.js.


2
То, что вы говорите о @kaasdude .... этот метод эффективно удаляет расширение на узле., Не уверен, что вы хотели выразить, но этот метод работает жемчужинами.
— Эрик

1
Этот ответ довольно ограничен серверным узлом. Если вы попытаетесь использовать это в реагирующем коде, это не похоже на импорт.
— Чарли

1
если вы хотите удалить расширение из пути, включая каталоги, вы можете сделать, var parsed = path.parse(filename)после чего path.join(parsed.dir, parsed.name).
— Jespertheend

Другая возможность есть let base = path.basename( file_path, path.extname( file_path ) ).
— Бикарлсен

116

x.length-4учитывает только расширения 3 символов. Что делать, если у вас есть filename.jpegили filename.pl?

РЕДАКТИРОВАТЬ:

Чтобы ответить ... конечно, если у вас всегда есть расширение .jpg, x.length-4будет работать просто отлично.

Однако, если вы не знаете длину своего расширения, любое из ряда решений будет лучше / надежнее.

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

ИЛИ

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

ИЛИ

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

ИЛИ (при условии, что имя файла имеет только одну точку)

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

ИЛИ (также только с одной точкой)

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

12
?? Вы можете иметь имя файла ex: "summer.family.jpg", в этом случае split ('.') [0] вернет только частичное имя файла. Я бы убрал его из ответа или четко указал под вопросом для этого примера. @basarat ...
— Roko C. Buljan

Что-то, что я часто делаю в отношении расщепления деталей:var parts = full_file.split("."); var ext = parts[parts.length-1]; var file = parts.splice(0,parts.length-1).join(".");
— radicand

x.split (".") даже не следует считать ответом. Я знаю, что использую «.» почти во всех моих соглашениях об именах файлов, например: survey.controller.js или my.family.jpg.
— Ли Бриндли

@ Lee2808: Отсюда и предупреждение только об одной точке. Это просто означает, что существует несколько подходов, в зависимости от приложения. Я бы, конечно, использовал один из других методов почти во всех случаях.
— Джефф Б

x = x.substr(0, x.lastIndexOf('.'));- ты наверное имел ввиду x = x.substring(0, x.lastIndexOf('.'));?
— Дзяд Боровы

39

Возможно, вы можете использовать предположение, что последняя точка будет разделителем расширения.

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

Если файл не имеет расширения, он вернет пустую строку. Чтобы исправить это используйте эту функцию

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

Предупреждение, это не удастся, если не будет никакого расширения имени файла. Вы остались с пустой строкой.
— Брэд

18
Укороченная версия, в которой нет точек. var f = x.substr(0, x.lastIndexOf('.')) || x;Это работает, потому что пустая строка ложная, поэтому она возвращает x.
— Джонатан Ровни

22

Мне нравится этот, потому что это один лайнер, который не слишком трудно читать:

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


12

Это работает, даже если в строке нет разделителя.

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"

Может также использоваться как однострочный:

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

РЕДАКТИРОВАТЬ: Это более эффективное решение:

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

10

Я не знаю, если это правильный вариант, но я использую это:

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.

Это не просто одна операция, которую я знаю, но, по крайней мере, она всегда должна работать!

ОБНОВЛЕНИЕ: Если вы хотите oneliner, вот вы:

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


1
Это должен быть не name.join (''), а name.join ('.'). Вы разделяете по точкам, но присоединяетесь через запятую, поэтому hello.name.txtвозвращаетесьhello, name
— Зло


7

Вот еще одно решение на основе регулярных выражений:

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

Это должно только отрубить последний сегмент.


7

Простой:

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

6

Принятый ответ удаляет только последнюю часть расширения ( .jpeg), что может быть хорошим выбором в большинстве случаев.

Однажды мне пришлось удалить все расширения ( .tar.gz), а имена файлов были ограничены, чтобы не содержать точек (так 2015-01-01.backup.tarчто это не будет проблемой):

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

4
var fileName = "something.extension";
fileName.slice(0, -path.extname(fileName).length) // === "something"

Пока это единственный метод, который работает для полных путей: path/name.ext-> paht/nameвместо простого возврата name, но я бы предпочел сделать с этим, fs.parseхотя он немного более многословен: stackoverflow.com/a/59576950/895245
— Ciro Santilli 郝海东 冠状 病法轮功 事件 法轮功

3

Если вам нужно обработать переменную, которая содержит полный путь (например, thePath = "http://stackoverflow.com/directory/subdirectory/filename.jpg"), и вы хотите вернуть только «имя файла», вы можете использовать:

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

результатом будет имя == "имя файла" ;

Чтобы попробовать это, напишите следующую команду в окне консоли вашего отладчика Chrome: window.location.pathname.split("/").slice(-1).join().split(".").shift()

Если вам нужно обработать только имя файла и его расширение (например:) theNameWithExt = "filename.jpg":

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

результат будет theName == "filename" , такой же, как указано выше;

Ноты:

  1. Первый немного медленнее, потому что выполняет больше операций; но работает в обоих случаях, другими словами, он может извлечь имя файла без расширения из заданной строки, содержащей путь или имя файла с помощью ex. В то время как второй работает, только если данная переменная содержит имя файла с ext, например filename.ext, но немного быстрее.
  2. Оба решения работают как с локальными, так и с серверными файлами;

Но я не могу ничего сказать ни о сравнении производительности с другими ответами, ни о совместимости браузера или ОС.

рабочий фрагмент 1: полный путь

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

рабочий фрагмент 2: имя файла с расширением

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

рабочий фрагмент 2: имя файла с двойным расширением

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


3

Хотя уже довольно поздно, я добавлю другой подход, чтобы получить имя файла без расширения, используя старый добрый JS-

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


или path.split('.').pop()для одной части расширения файла
— mixdev

На самом деле он пытался получить имя файла, а не расширение!
— Муним Дибош

3

Node.js удаляет расширение из каталога полного пути

https://stackoverflow.com/a/31615711/895245 например сделал path/hello.html-> hello, но если вы хотите path/hello.html-> path/hello, вы можете использовать это:

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

также выводит каталог:

path/hello

https://stackoverflow.com/a/36099196/895245 также достигает этого, но я считаю этот подход немного более семантически приятным.

Протестировано в Node.js v10.15.2.


0

Здесь регулярные выражения пригодятся! .replace()Метод Javascript будет принимать регулярное выражение, и вы можете использовать его для достижения желаемого:

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

0

Еще один лайнер - мы предполагаем, что наш файл - это изображение jpg >> ex: var yourStr = 'test.jpg';

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

0

Ты можешь использовать path для маневра.

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

Вывод

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


0

Это код, который я использую для удаления расширения из имени файла без использования регулярных выражений или indexOf (indexOf не поддерживается в IE8). Предполагается, что расширением является любой текст после последнего '.' персонаж.

Это работает для:

  • файлы без расширения: "myletter"
  • файлы с '.' в названии: "my.letter.txt"
  • неизвестная длина расширения файла: "my.letter.html"

Вот код:

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;
}

не с hello.tar.gz, выход есть hellotar.
— Асиф Али

#AsifAli спасибо, вы правы, я забыл прочитать расширение файла. Я обновил ответ, надеюсь, он работает сейчас.
— Маленький мозг

-3

Я бы использовал что-то вроде x.substring (0, x.lastIndexOf ('.')). Если вы стремитесь к производительности, вообще не используйте javascript :-p Нет, еще одно утверждение действительно не имеет значения для 99,9999% всех целей.


2
«Если вы стремитесь к производительности, вообще не используйте javascript» - Что еще вы предлагаете использовать в веб-приложениях?
— TJ

Он не упоминает веб-приложения.
— Лукас Моескопс

1
Этот вопрос был задан, и ответ был опубликован в 2010 году, 7 лет назад, и JavaScript в значительной степени использовался только в веб-приложениях. (Узел только что родился, в то время у него даже не было гида или NPM)
— TJ

;-) Тем не менее, если производительность имеет значение для таких задач, как это, вы можете рассмотреть возможность сделать это на бэкэнде и обработать результаты на веб-интерфейсе.
— Лукас Моескопс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.