10
\$\begingroup\$

Your challenge is to find the file extension of a provided filename:

hi.txt -> txt or .txt
carrot.meme -> meme or .meme
lol (undefined behavior)
what..is..this..file -> file or .file
.bashrc -> bashrc or .bashrc
T00M@n3KaPZ.h0wC[]h -> h0wC[]h or .h0wC[]h
agent.000 -> 000 or .000

You must get the text from the last . or after the last . to the end of the string. The first capturing group match of the regular expression /\.([^.]+)$/ works, and so does splitting the input on .s and returning the last one.

The file name will always contain at least one ., but it may contain multiple .. (see examples)

The input will always match ^[.a-zA-Z0-9^!\[\]{}@$%+=]+$.

\$\endgroup\$
  • 17
    \$\begingroup\$ Please consider using the Sandbox in the future to get feedback on your challenges before posting them to the main site. \$\endgroup\$ – Mego May 16 '17 at 20:45
  • 1
    \$\begingroup\$ codegolf.meta.stackexchange.com/a/12432/59376 - Got this idea from your challenge. \$\endgroup\$ – Magic Octopus Urn May 16 '17 at 21:51
  • \$\begingroup\$ @carusocomputing nice challenge! \$\endgroup\$ – programmer5000 May 17 '17 at 0:06
  • 1
    \$\begingroup\$ why the negative votes? Is this challenge "exceedingly trivial" or so ? \$\endgroup\$ – Abel Tom May 17 '17 at 5:09
  • \$\begingroup\$ @AbelTom edit history would suggest downvotes were for the lack of specifications in the first draft of this question. \$\endgroup\$ – Patrick Roberts May 17 '17 at 5:12

86 Answers 86

15
\$\begingroup\$

Retina, 5 bytes

.*\.

Replaces everything and a dot with nothing at all.

Try it online!

\$\endgroup\$
11
\$\begingroup\$

JavaScript (ES6), 19 bytes

Returns the full filename when there's no file extension. I suppose this is an acceptable undefined behavior.

let f =

s=>s.split`.`.pop()

console.log(f("hi.txt"))               // -> txt
console.log(f("carrot.meme"))          // -> meme
console.log(f("lol"))                  // -> undefined behavior
console.log(f("what..is..this..file")) // -> file
console.log(f("T00M@n3KaPZ.h0wC[]h")) // -> h0wC[]h
console.log(f(".bashrc")) // -> bashrc

\$\endgroup\$
  • \$\begingroup\$ The point of undefined behavior is that anything goes. Although, nasal demons, while still undefined behavior, might fail the "no malicious programs" clause. \$\endgroup\$ – John Dvorak May 27 '17 at 11:26
10
\$\begingroup\$

Mathematica, 13 22 bytes

Edit: Not sure how I missed the ".bashrc" test case. Thanks to Artyer for keeping me honest.

FileExtension["a"<>#]&

If the input matches \.[^.]+, then FileExtension just returns the empty string, so we prepend the letter a. In any other case, prepending a doesn't affect output of FileExtension.

\$\endgroup\$
  • 11
    \$\begingroup\$ A Mathematica builtin...no surprise. \$\endgroup\$ – programmer5000 May 16 '17 at 21:03
  • 1
    \$\begingroup\$ I'd be surprised if there weren't any mathematica builtins for any question possible \$\endgroup\$ – sagiksp May 17 '17 at 5:52
  • \$\begingroup\$ I don't have access to Mathematica, but I would suspect that .ext would result in nothing, which failes for .bashrc needing to output bashrc (It fails in Mathics) \$\endgroup\$ – Artyer May 17 '17 at 11:22
  • \$\begingroup\$ Apparently it works \$\endgroup\$ – programmer5000 May 17 '17 at 11:36
  • \$\begingroup\$ Mathematica just needs to meta built-ins Create Built-in XXXXXXXX. \$\endgroup\$ – Magic Octopus Urn May 17 '17 at 13:02
9
\$\begingroup\$

Pure bash, 13

echo ${1##*.}

Try it online.

\$\endgroup\$
7
\$\begingroup\$

Japt, 3 bytes

2 bytes of code, +1 for the h flag.

q.

Explanation:

q.       Split the input by `.`
   -h    Return the last item

Try it online!

\$\endgroup\$
7
\$\begingroup\$

05AB1E, 4 bytes

'.¡¤

Try it online! or Try All Tests

'.   # Push '.'
  ¡  # Split on occurrences of '.'
   ¤ # Tail
\$\endgroup\$
  • \$\begingroup\$ What? I've never seen a split occurences in the wiki. Edit: Now I found it! \$\endgroup\$ – facepalm42 Jul 18 at 11:09
7
\$\begingroup\$

c function, 21

  • 1 byte saved thanks to @Dennis.
  • 3 bytes saved thanks to @JohanduToit.
  • 2 bytes saved thanks to @Neil.
  • 1 byte saved thanks to @algmyr.
f(s){s=rindex(s,46);}

Try it online.

\$\endgroup\$
  • 1
    \$\begingroup\$ If you're ok with using legacy POSIX functions you could use rindex to save a byte. \$\endgroup\$ – algmyr May 17 '17 at 19:15
  • \$\begingroup\$ @algmyr Sure, it works fine on TIO, so I'll use it. I'd never heard of rindex() before - thanks for the tip! \$\endgroup\$ – Digital Trauma May 17 '17 at 19:34
5
\$\begingroup\$

PHP, 21 Bytes

<?=pathinfo($argn,4);

Try it online!

is a shorter expression for

<?=pathinfo($argn)[extension];

pathinfo

PHP, 27 Bytes

<?=end(explode(".",$argn));

explode

Try it online!

PHP <7.0, 26 Bytes

<?=end(split("\.",$argn));

deprecated split

\$\endgroup\$
  • 1
    \$\begingroup\$ Are you counting a trailing newline for the first one? It should be 27 bytes, not 28. \$\endgroup\$ – Conor O'Brien May 16 '17 at 21:45
  • \$\begingroup\$ @ConorO'Brien Thank You .I have count after copy and paste from the split version a `` \$\endgroup\$ – Jörg Hülsermann May 16 '17 at 21:49
  • 2
    \$\begingroup\$ The pathinfo() based one could be <?=pathinfo($argn,4);. \$\endgroup\$ – manatwork May 17 '17 at 11:56
4
\$\begingroup\$

Neo4j Cypher, 24 bytes

return split($i,".")[-1]

Input is in a param (i), probably the only way for cypher to take input. Pretty straightforward. Cypher has never been used on PPCG before

\$\endgroup\$
4
\$\begingroup\$

GNU Make, 12 bytes

$(suffix $1)

Not using a builtin, 27 bytes:

$(lastword $(subst ., ,$1))
\$\endgroup\$
4
\$\begingroup\$

Batch, 10 bytes

@echo %~x1

Strangely competitive for once.

\$\endgroup\$
4
\$\begingroup\$

V, 5, 3 bytes

Since more of this answer is unprintable than printable, here is a hexdump:

00000000: cd81 ae                                  ...

Try it online!

This uses Jan Dvorak's algorithm, it just happens to be a more efficient encoding of it.

Explanation:

Í       " Remove all occurrences of:
 0x81   "   Anything (greedy)
     ®  "   Followed by a dot 

Old solution:

$T.d|
\$\endgroup\$
  • \$\begingroup\$ Explanation please? \$\endgroup\$ – Erik the Outgolfer May 17 '17 at 13:18
  • \$\begingroup\$ @EriktheOutgolfer Done \$\endgroup\$ – DJMcMayhem May 17 '17 at 16:39
  • \$\begingroup\$ Wait ® means followed by a dot? Lol that's weird. \$\endgroup\$ – Erik the Outgolfer May 17 '17 at 16:42
3
\$\begingroup\$

sed, 8 bytes

s:.*\.::

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Jelly, 4 bytes

ṣ”.Ṫ

A monadic link taking the file name and returning the extension with no leading ..

Try it online!

How?

Literally does what was asked...

ṣ”.Ṫ - Main link: list of characters, f
 ”.  - literal '.'
ṣ    - split f at occurrences of '.'
   Ṫ - tail (get the last chunk)
\$\endgroup\$
3
\$\begingroup\$

Go, 85 bytes

Go is... troublesome.

import(."fmt"
."os"
."strings")
func main(){s:=Split(Args[1],".");Print(s[len(s)-1])}

Try it online!

A sample of parentheses from the code:

()(){([])([()])}
\$\endgroup\$
  • 2
    \$\begingroup\$ ()(){([])([()])} — is it a valid Brain-Flak? \$\endgroup\$ – eush77 May 16 '17 at 21:08
  • 5
    \$\begingroup\$ @eush77 It's technically valid Brain-Flak, since it will run without errors, but it doesn't do anything interesting/useful. It's either just the literal 2 with no instructions/commands or anything or an infinite loop that continuously allocates more memory, depending on input. \$\endgroup\$ – DJMcMayhem May 16 '17 at 21:27
  • \$\begingroup\$ Using filepath.Ext will save you a few bites \$\endgroup\$ – powelles May 16 '17 at 22:17
3
\$\begingroup\$

JavaScript (ES6), 33 31 28 bytes

s=>s.slice(s.lastIndexOf`.`)

Spec change in comments removes the need for +1.

-3 bytes thanks to nderscore

\$\endgroup\$
  • 1
    \$\begingroup\$ -3 with slice and template string execution: s=>s.slice(s.lastIndexOf`.`) \$\endgroup\$ – nderscore May 16 '17 at 21:42
3
\$\begingroup\$

Common Lisp, 57 bytes

(lambda(s)(#1=reverse(subseq #2=(#1# s)0(search"."#2#))))

Try it online (added some bytes to call this anonymous function and display returned string)

Explanation

(#1=reverse ...)     ;reverse is now accessible with #1# - saves 1 byte. I 
                     ;also need to reverse output of function inside to 
                     ;get extension in correct order
#2=(#1# s)           ;reverse of input string is now accessible with #2#
(search"."#2#)       ;I take reversed string and search for "." to get position of 
                     ;first instance of "." in string from the end of it
(subseq ... 0 ...)   ;get part of reversed string, 
                     ;starting from first character and ending just 
                     ;before first occurance of "."
                     ;this gives reversed extension

I get substring of reversed string, starting from 0, ending on this

\$\endgroup\$
3
\$\begingroup\$

Gema, 3 characters

*.=

Sample run:

bash-4.4$ gema '*.=' <<< 'what..is..this..file'
file
\$\endgroup\$
3
\$\begingroup\$

MATL, 8 7 bytes

46&YbO)

Try it at MATL Online!

Explanation

        % Implicitly grab input as string
46      % ASCII for '.'
&Yb     % Split the input string at the '.' characters
O)      % Retrieve just the last part
        % Implicitly print the result
\$\endgroup\$
3
\$\begingroup\$

Javascript (ES5), 38 bytes

function(s){return s.split(".").pop()}
\$\endgroup\$
  • 2
    \$\begingroup\$ Just so you know, the downvote was cast automatically by the Community user when your answer was edited. I consider this a bug. \$\endgroup\$ – Dennis May 16 '17 at 22:57
  • \$\begingroup\$ plz fix that if you can! \$\endgroup\$ – Sinned May 17 '17 at 0:56
3
\$\begingroup\$

C#, 33 41 bytes

a=>a.Split('.').Last();

Edit as suggested:

using System.Linq;a=>a.Split('.').Last();
\$\endgroup\$
  • 1
    \$\begingroup\$ You need to include using Sytem.Linq; into your byte count \$\endgroup\$ – TheLethalCoder May 17 '17 at 12:17
  • \$\begingroup\$ And also a=>a.Split('.').Last(); implicit return is shorter \$\endgroup\$ – TheLethalCoder May 17 '17 at 12:18
  • \$\begingroup\$ @TheLethalCoder Thanks for suggested fixes, still new to this :) \$\endgroup\$ – LiefdeWen May 17 '17 at 12:23
  • \$\begingroup\$ I'm surprised this is longer than my solution using Path... \$\endgroup\$ – TheLethalCoder May 17 '17 at 13:03
3
\$\begingroup\$

Awk, 14 13 characters

(10 9 characters code + 4 characters command line option.)

{$0=$NF}1

Thanks to:

  • Robert Benson for spotting the unnecessary semicolon (-1 character)

Sample run:

bash-4.4$ awk -F. '{$0=$NF}1' <<< $'hi.txt\ncarrot.meme\nlol\nwhat..is..this..file\n.bashrc\nT00M@n3KaPZ.h0wC[]h'
txt
meme
lol
file
bashrc
h0wC[]h
\$\endgroup\$
  • \$\begingroup\$ You don't need the ;. and just FYI, awk '{$0=$NF}1 works, no command line option needed. Oh... I must be tired. I see what you did there. You do need the command line option. \$\endgroup\$ – Robert Benson May 17 '17 at 18:18
  • 1
    \$\begingroup\$ Thank you, @RobertBenson. I have no idea why I put that ; there. \$\endgroup\$ – manatwork May 17 '17 at 18:53
3
\$\begingroup\$

Lua, 53 30 bytes

Replaces everything upto the last . with the empty string ''.

Double parenthesis to select only the first return value of gsub.

Any golfing tips are welcome, I'm rusty in lua...

print(((...):gsub('.*%.','')))

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Java 8, 52 27 bytes

s->s.replaceAll(".*\\.","")

Try it here.

Replace everything before the last dot (and the dot itself) with nothing.

This is shorter than using split (s->s.split("\\.")[s.split("\\.").length-1];) or substring (s->s.substring(s.lastIndexOf('.'));).

\$\endgroup\$
3
\$\begingroup\$

Taxi, 1397 bytes

Go to Post Office:w 1 l 1 r 1 l.Pickup a passenger going to Chop Suey.Go to Chop Suey:n 1 r 1 l 4 r 1 l.[a]Pickup a passenger going to Narrow Path Park.Go to Narrow Path Park:n 1 l 1 r 1 l.Go to Chop Suey:e 1 r 1 l 1 r.Switch to plan "b" if no one is waiting.Switch to plan "a".[b]Go to The Babelfishery:n 1 l 1 l.[c]Go to Fueler Up:n.Go to Joyless Park:n 2 r.Go to Narrow Path Park:w 1 r 3 l.Pickup a passenger going to Cyclone.Go to Cyclone:w 1 l 1 r 2 l.Pickup a passenger going to Crime Lab.Pickup a passenger going to Joyless Park.'.' is waiting at Writer's Depot.Go to Writer's Depot:s.Pickup a passenger going to Crime Lab.Go to Crime Lab:n 1 r 2 r 2 l.Switch to plan "c" if no one is waiting.Go to Narrow Path Park:n 5 l.[d]Pickup a passenger going to Chop Suey.Go to Chop Suey:e 1 r 1 l 1 r.Go to Narrow Path Park:n 1 l 1 r 1 l.Switch to plan "e" if no one is waiting.Switch to plan "d".[e]Go to Joyless Park:e 1 r 3 l.Switch to plan "f" if no one is waiting.Pickup a passenger going to Narrow Path Park.Go to Fueler Up:w 1 l.Go to Narrow Path Park:n 4 l.Switch to plan "e".[f]Go to Narrow Path Park:w 1 r 3 l.[g]Switch to plan "h" if no one is waiting.Pickup a passenger going to KonKat's.Go to KonKat's:e 1 r.Pickup a passenger going to KonKat's.Go to Narrow Path Park:n 2 l.Switch to plan "g".[h]Go to KonKat's:e 1 r.Pickup a passenger going to Post Office.Go to Post Office:s 3 r 1 l.

Try it online!

Taxi doesn't have a reverse function so this ballooned pretty quickly. The logic is:

  1. Break the string into characters
  2. Reverse the array
  3. Iterate through each until a period is found, storing each in a FIFO array
  4. Empty the array (because there's only one LIFO array available)
  5. Dump the FIFO array into the LIFO array
  6. Concatenate the LIFO array and output
\$\endgroup\$
3
\$\begingroup\$

Vim, 5 bytes

$F.d0

Explanation: find last . in line, delete everything before it

Another, longer, but in my opinion still interesting approach with 9 bytes (notice the trailing new line)

d/.*\./e

This one works similarly, 5 bytes (again, trailing new line):

d?\.

\$\endgroup\$
2
\$\begingroup\$

Brain-Flak, 84 bytes

Includes +2 for -rc

(()){{}([((((()()()){}())()){}{}){}]({}<>)<>)({()(<{}>)}{})}{}{{}}<>{}{({}<>)<>}<>

Try it online!

# Push 1 to start the loop
(())

# Start loop
{{}

  # If TOS == 46 i.e. '.'
  ([((((()()()){}())()){}{}){}]({}<>)<>)({()(<{}>)}{})
  # ^------------------------^ ^-------^ 
  #           This is 46         Also, copy TOS to other stack

# End loop after the first '.'
}{}

# Delete everything from this stack
{{}}

# Delete the '.' that got copied
<>{}

# Copy everything back to reverse it to the correct order
{({}<>)<>}<>
\$\endgroup\$
2
\$\begingroup\$

Japt, 6 5 bytes

q'. o

Try it online!

Explanation

 q'. o
Uq'. o
Uq'.    # Split the input at "."
     o # Return the last item
\$\endgroup\$
  • \$\begingroup\$ When you only need to return the last item of an array, you can use o in place of gJ. (Learned that trick from @obarakon a while back) \$\endgroup\$ – ETHproductions May 16 '17 at 23:38
2
\$\begingroup\$

jq, 15 14 characters

(11 10 characters code + 4 characters command line options.)

./"."|last

Sample run:

bash-4.4$ jq -Rr './"."|last' <<< 'what..is..this..file'
file

On-line test

\$\endgroup\$
2
\$\begingroup\$

Octave, 24 bytes

@(x)strsplit(x,'.'){end}

Creates an anonymous function named ans which can accept a string as input

Online Demo

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.