Как обрезать расширение файла из строки в 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()является функцией и проверкой символов.

ma11hew28
источник
Почти так же, как 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
jakubiszon
источник
17

В версиях Node.js до 0.12.x:

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

Конечно, это также работает в 0.12.x и позже.

blah238
источник
path.parseОтвет проще.
Дан Даскалеску
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

Еще один вкладыш:

x.split(".").slice(0, -1).join(".")
Джейкоб Бундгаард
источник
7

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

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

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

Чед Джонсон
источник
7

Простой:

var n = str.lastIndexOf(".");
return n > -1 ? str.substr(0, n) : str;
Dugh
источник
6

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

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

var name = "2015-01-01_backup.tar.gz";
name.replace(/(\.[^/.]+)+$/, "");
basic6
источник
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");
Alex
источник
0

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

    yourStr = yourStr.slice(0, -4); // 'test'
SorinN
источник
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
x.slice(0, -(x.split('.').pop().length + 1));
ishandutta2007
источник
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
;-) Тем не менее, если производительность имеет значение для таких задач, как это, вы можете рассмотреть возможность сделать это на бэкэнде и обработать результаты на веб-интерфейсе.
Лукас Моескопс