Pergunta

I have the following string:

/path1/path2/foo.bar.qux.txt

What I want to do is to extract the basename by specifying the extension. If I define the extension to be .bar.qux.txt then the base name is "foo". Then if the extension is .qux.txt then the base is: foo.bar.

Perl has the following function:

use File::Basename;
my $longones = "/path1/path2/foo.bar.qux.txt";
my $base = basename($longones,"*.bar.qux.txt");
print "$base\n";

What's the Python way to do it?

Foi útil?

Solução

There's no built-in function that does what you want. os.path.splitext doesn't allow to define what should be considered an extension. In fact the name basename for the perl function is a misnaming because in *NIX basename does contain the extension.

However you can combine os.path.basename with a rsplit:

>>> import os
>>> os.path.basename('/path1/path2/foo.bar.qux.txt').rsplit('.bar.qux.txt')[0]
'foo'
>>> os.path.basename('/path1/path2/foo.bar.qux.txt').rsplit('.qux.txt')[0]
'foo.bar'

Note that if the filename contains the extension you might get a wrong result:

>>> os.path.basename('/path1/path2/foo.bar.qux.txt.foo.bar.qux.txt').rsplit('.qux.txt')[0]
'foo.bar'

However you can always specify a maxsplit of 1 to only split the first extension:

>>> os.path.basename('/path1/path2/foo.bar.qux.txt.foo.bar.qux.txt').rsplit('.qux.txt', maxsplit=1)[0]
'foo.bar.qux.txt.foo.bar'

In python2 you must specify the second argument positionally as rsplit(text, 1).

Alternatively use rpartition:

>>> os.path.basename('/path1/path2/foo.bar.qux.txt.foo.bar.qux.txt').rpartition('.qux.txt')[0]
'foo.bar.qux.txt.foo.bar'

A solution with regexes could be:

import re

def basename_without_ext(path, ext):
    regex = re.compile('{}$'.format(re.escape(ext)))
    return regex.sub('', os.path.basename(path))

Used as:

>>> basename_without_ext('/path1/path2/foo.bar.qux.txt.foo.bar.qux.txt', '.qux.txt')
'foo.bar.qux.txt.foo.bar'
>>> basename_without_ext('/path1/path2/foo.bar.qux.txt', '.bar.qux.txt')
'foo'

Outras dicas

Python has os.path.basename but it doesn't let you define the extension though:

import os
os.path.basename(filename)

Using str.endswith() and slicing seems easy enough though.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top