File extension is in extensions list: Difference between revisions

Added Easylang
(→‎{{header|Haskell}}: Added a version using isSuffixOf (and avoiding the gzip false positive of the draft above))
(Added Easylang)
 
(43 intermediate revisions by 24 users not shown)
Line 1:
{{draft task}} [[Category:File_System_Operations]] [[Category:String_manipulation]]
[[Category:String_manipulation]]
 
{{task}}
[[wp:Filename extension|Filename extensions]] are a rudimentary but commonly used way of identifying files types.
 
{{task heading}}
 
;Task:
Given an arbitrary filename and a list of extensions, tell whether the filename has one of those extensions.
 
 
Notes:
Line 22 ⟶ 25:
The following test cases all assume this list of extensions: &nbsp; <code>zip</code>, <code>rar</code>, <code>7z</code>, <code>gz</code>, <code>archive</code>, <code>A##</code>
 
:::::::: {| class="wikitable"
|-
! Filename
Line 42 ⟶ 45:
If your solution does the extra credit requirement, add <code>tar.bz2</code> to the list of extensions, and check the following additional test cases:
 
:::::::: {| class="wikitable"
|-
! Filename
Line 60 ⟶ 63:
For these reasons, this task exists in addition to the [[Extract file extension]] task.
 
{{task heading|Related tasks}}
 
;Related tasks:
* [[Extract file extension]]
* [[String matching]]
<br><br>
 
=={{header|11l}}==
<hr>
{{trans|Python}}
 
<syntaxhighlight lang="11l">F is_ext(file_name, extensions)
R any(extensions.map(e -> @file_name.lowercase().ends_with(‘.’e.lowercase())))
 
F test(file_names, extensions)
L(file_name) file_names
print(file_name.ljust(max(file_names.map(f_n -> f_n.len)))‘ ’String(is_ext(file_name, extensions)))
 
test([‘MyData.a##’, ‘MyData.tar.Gz’, ‘MyData.gzip’, ‘MyData.7z.backup’, ‘MyData...’, ‘MyData’], [‘zip’, ‘rar’, ‘7z’, ‘gz’, ‘archive’, ‘A##’, ‘tar.bz2’])
test([‘MyData_v1.0.tar.bz2’, ‘MyData_v1.0.bz2’], [‘tar.bz2’])</syntaxhighlight>
 
{{out}}
<pre>
MyData.a## 1B
MyData.tar.Gz 1B
MyData.gzip 0B
MyData.7z.backup 0B
MyData... 0B
MyData 0B
MyData_v1.0.tar.bz2 1B
MyData_v1.0.bz2 0B
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
 
CHAR FUNC ToLower(CHAR c)
IF c>='A AND c<='Z THEN
c==+'a-'A
FI
RETURN (c)
 
BYTE FUNC CheckExt(CHAR ARRAY file,ext)
BYTE i,j
CHAR c1,c2
 
i=file(0) j=ext(0)
IF i<j THEN RETURN (0) FI
 
WHILE j>0
DO
c1=ToLower(file(i))
c2=ToLower(ext(j))
IF c1#c2 THEN RETURN (0) FI
i==-1
j==-1
OD
IF file(i)#'. THEN
RETURN (0)
FI
RETURN (1)
 
BYTE FUNC Check(CHAR ARRAY file PTR ARRAY exts BYTE count)
BYTE i
 
FOR i=0 TO count-1
DO
IF CheckExt(file,exts(i)) THEN
RETURN (1)
FI
OD
RETURN (0)
 
PROC Main()
PTR ARRAY exts(7),files(8)
BYTE i
 
exts(0)="zip"
exts(1)="rar"
exts(2)="7z"
exts(3)="gz"
exts(4)="archive"
exts(5)="A##"
exts(6)="tar.bz2"
 
files(0)="MyData.a##"
files(1)="MyData.tar.Gz"
files(2)="MyData.gzip"
files(3)="MyData.7z.backup"
files(4)="MyData..."
files(5)="MyData"
files(6)="MyData_v1.0.tar.bz2"
files(7)="MyData_v1.0.bz2"
 
FOR i=0 to 7
DO
Print(files(i)) Print(" -> ")
IF Check(files(i),exts,7) THEN
PrintE("true")
ELSE
PrintE("false")
FI
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/File_extension_is_in_extensions_list.png Screenshot from Atari 8-bit computer]
<pre>
MyData.a## -> true
MyData.tar.Gz -> true
MyData.gzip -> false
MyData.7z.backup -> false
MyData... -> false
MyData -> false
MyData_v1.0.tar.bz2 -> true
MyData_v1.0.bz2 -> false
</pre>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Fixed.Equal_Case_Insensitive; use Ada.Strings.Fixed;
with Ada.Strings.Bounded;
 
procedure Main is
 
package B_String is new Ada.Strings.Bounded.Generic_Bounded_Length (30);
use B_String;
function is_equal (left, right : String) return Boolean renames
Ada.Strings.Fixed.Equal_Case_Insensitive;
 
type extension_list is array (Positive range <>) of Bounded_String;
Ext_List : extension_list :=
(To_Bounded_String ("zip"), To_Bounded_String ("rar"),
To_Bounded_String ("7z"), To_Bounded_String ("gz"),
To_Bounded_String ("archive"), To_Bounded_String ("A##"),
To_Bounded_String ("tar.bz2"));
type filename_list is array (Positive range <>) of Bounded_String;
fnames : filename_list :=
(To_Bounded_String ("MyData.a##"), To_Bounded_String ("MyData.tar.Gz"),
To_Bounded_String ("MyData.gzip"), To_Bounded_String ("MyData..."),
To_Bounded_String ("Mydata"), To_Bounded_String ("MyData_V1.0.tar.bz2"),
To_Bounded_String ("MyData_v1.0.bz2"));
Valid_Extension : Boolean;
begin
for name of fnames loop
Valid_Extension := False;
Put (To_String (name));
for ext of Ext_List loop
declare
S : String := "." & To_String (ext);
T : String := Tail (Source => To_String (name), Count => S'Length);
begin
if is_equal (S, T) then
Valid_Extension := True;
end if;
end;
end loop;
Set_Col (22);
Put_Line (": " & Valid_Extension'Image);
end loop;
end Main;</syntaxhighlight>
{{out}}
<pre>
MyData.a## : TRUE
MyData.tar.Gz : TRUE
MyData.gzip : FALSE
MyData... : FALSE
Mydata : FALSE
MyData_V1.0.tar.bz2 : TRUE
MyData_v1.0.bz2 : FALSE
</pre>
 
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
<langsyntaxhighlight lang="algol68"># returns the length of str #
OP LENGTH = ( STRING str )INT: ( UPB str - LWB str ) + 1;
# returns TRUE if str ends with ending FALSE otherwise #
Line 146 ⟶ 311:
# test the file names in the extra credit #
test has extension in list( "MyData_v1.0.tar.bz2", ec extensions, TRUE );
test has extension in list( "MyData_v1.0.bz2", ec extensions, FALSE )</langsyntaxhighlight>
{{out}}
<pre>
Line 157 ⟶ 322:
MyData_v1.0.tar.bz2 has extension "tar.bz2"
MyData_v1.0.bz2 does not have an extension in the list</pre>
 
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">ext←{
ex←⎕C'.',¨⍺
ex∨.≡(-≢¨ex)↑¨⊂⎕C⍵
}
 
test←{
e←'zip' 'rar' '7z' 'gz' 'archive' 'A##' 'tar.bz2'
f←'MyData.a##' 'MyData.tar.Gz' 'MyData.gzip' 'MyData.7z.backup'
f,←'MyData...' 'MyData' 'MyData_v1.0.tar.bz2' 'MyData_V1.0.bz2'
f,[1.5]e∘ext¨f
}</syntaxhighlight>
{{out}}
<pre> MyData.a## 1
MyData.tar.Gz 1
MyData.gzip 0
MyData.7z.backup 0
MyData... 0
MyData 0
MyData_v1.0.tar.bz2 1
MyData_V1.0.bz2 0</pre>
 
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">fileExtensions: map ["zip" "rar" "7z" "gz" "archive" "A##"] => ["." ++ lower &]
hasExtension?: function [file][
in? extract.extension lower file
fileExtensions
]
files: ["MyData.a##" "MyData.tar.Gz" "MyData.gzip" "MyData.7z.backup" "MyData..." "MyData"]
 
loop files 'file ->
print [file "=> hasExtension?:" hasExtension? file]</syntaxhighlight>
{{out}}
 
<pre>MyData.a## => hasExtension?: true
MyData.tar.Gz => hasExtension?: true
MyData.gzip => hasExtension?: false
MyData.7z.backup => hasExtension?: false
MyData... => hasExtension?: false
MyData => hasExtension?: false</pre>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">
fileList := "MyData.a##,MyData.tar.Gz,MyData.gzip,MyData.7z.backup,MyData...,MyData,MyData_v1.0.tar.bz2,MyData_v1.0.bz2"
extList := "zip,rar,7z,gz,archive,A##,tar.bz2"
textOut := "File extension is in list (" extList ") ?`n"
loop,parse,fileList,CSV
{
textOut .= A_LoopField " ---> "
lastDotPos := InStr(A_LoopField,".",0,0)
extloop := SubStr(A_LoopField,lastDotPos+1)
if (extloop = "bz2")
{
lastDotPos := InStr(A_LoopField,".",0,0,2)
extloop := SubStr(A_LoopField,lastDotPos+1)
}
if !lastDotPos or !extloop
textOut .= "NO`n"
else if extloop in %extList%
textOut .= "YES`n"
else
textOut .= "NO`n"
}
MsgBox % textOut
ExitApp
</syntaxhighlight>
{{Out}}
<pre>File extension is in list (zip,rar,7z,gz,archive,A##,tar.bz2) ?
MyData.a## ---> YES
MyData.tar.Gz ---> YES
MyData.gzip ---> NO
MyData.7z.backup ---> NO
MyData... ---> NO
MyData ---> NO
MyData_v1.0.tar.bz2 ---> YES
MyData_v1.0.bz2 ---> NO</pre>
 
=={{header|AWK}}==
Line 162 ⟶ 408:
This solution meets the extended criteria stated in the problem.
 
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f FILE_EXTENSION_IS_IN_EXTENSIONS_LIST.AWK
BEGIN {
Line 184 ⟶ 430:
}
exit(0)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 196 ⟶ 442:
MyData_v1.0.bz2 extension is not in list
</pre>
 
 
=={{header|BASIC}}==
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="basic256">arraybase 1
dim extensions$ = {".zip", ".rar", ".7z", ".gz", ".archive", ".a##", ".tar.bz2"}
 
dim filenames$ = {"MyData.a##", "MyData.tar.gz", "MyData.gzip", "MyData.7z.backup", "MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"}
 
#dim as integer n, m
#dim as boolean flag
 
for n = 1 to filenames$[?]
flag = False
for m = 1 to extensions$[?]
if right(filenames$[n], length(extensions$[m])) = extensions$[m] then
flag = True
print filenames$[n]; " -> "; extensions$[m]; " -> "; " true"
exit for
end if
next m
if flag = False then print filenames$[n]; " -> "; "false"
next n
end</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
==={{header|FreeBASIC}}===
<syntaxhighlight lang="freebasic">Dim As String extensions(1 To 7) => {".zip", ".rar", ".7z", ".gz", ".archive", ".a##", ".tar.bz2"}
 
Dim As String filenames(1 To 8) => {"MyData.a##", "MyData.tar.gz", _
"MyData.gzip", "MyData.7z.backup", "MyData...", "MyData", _
"MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"}
 
Dim As Integer n, m
Dim As Boolean flag
 
For n = 1 To Ubound(filenames)
flag = False
For m = 1 To Ubound(extensions)
If Right(filenames(n), Len(extensions(m))) = extensions(m) Then
flag = True
Print filenames(n); " -> "; extensions(m); " -> "; " true"
Exit For
End If
Next m
If flag = False Then Print filenames(n); " -> "; "false"
Next n
Sleep</syntaxhighlight>
{{out}}
<pre>MyData.a## -> .a## -> true
MyData.tar.gz -> .gz -> true
MyData.gzip -> false
MyData.7z.backup -> false
MyData... -> false
MyData -> false
MyData_v1.0.tar.bz2 -> .tar.bz2 -> true
MyData_v1.0.bz2 -> false</pre>
 
==={{header|QBasic}}===
{{works with|QBasic}}
{{works with|QuickBasic}}
{{trans|FreeBASIC}}
<syntaxhighlight lang="qbasic">DIM extensions$(7)
FOR i = 1 TO 7
READ d$: extensions$(i) = d$
NEXT i
 
DIM filenames$(8)
FOR i = 1 TO 8
READ d$: filenames$(i) = d$
NEXT i
 
FOR n = 1 TO UBOUND(filenames$)
flag = 0
FOR m = 1 TO UBOUND(extensions$)
IF RIGHT$(filenames$(n), LEN(extensions$(m))) = extensions$(m) THEN
flag = 1
PRINT filenames$(n); " -> "; extensions$(m); " -> "; " true"
EXIT FOR
END IF
NEXT m
IF flag = 0 THEN PRINT filenames$(n); " -> "; "false"
NEXT n
END
 
DATA ".zip", ".rar", ".7z", ".gz", ".archive", ".a##", ".tar.bz2"
DATA "MyData.a##", "MyData.tar.gz", "MyData.gzip", "MyData.7z.backup"
DATA "MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"</syntaxhighlight>
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
==={{header|True BASIC}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="qbasic">DIM extensions$(7)
FOR i = 1 TO 7
READ d$
LET extensions$(i) = d$
NEXT i
DIM filenames$(8)
FOR i = 1 TO 8
READ d$
LET filenames$(i) = d$
NEXT i
FOR n = 1 TO UBOUND(filenames$)
LET flag = 0
FOR m = 1 TO UBOUND(extensions$)
IF (filenames$(n))[LEN(filenames$(n))-LEN(extensions$(m))+1:maxnum] = extensions$(m) THEN
LET flag = 1
PRINT filenames$(n); " -> "; extensions$(m); " -> "; " true"
EXIT FOR
END IF
NEXT m
IF flag = 0 THEN PRINT filenames$(n); " -> "; "false"
NEXT n
 
DATA ".zip", ".rar", ".7z", ".gz", ".archive", ".a##", ".tar.bz2"
DATA "MyData.a##", "MyData.tar.gz", "MyData.gzip", "MyData.7z.backup"
DATA "MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"
END</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="yabasic">dim extensions$(7)
for i = 1 to 7
read d$: extensions$(i) = d$
next i
 
dim filenames$(8)
for i = 1 to 8
read d$: filenames$(i) = d$
next i
 
for n = 1 to arraysize(filenames$(),1)
flag = 0
for m = 1 to arraysize(extensions$(),1)
if right$(filenames$(n), len(extensions$(m))) = extensions$(m) then
flag = 1
print filenames$(n), " -> ", extensions$(m), " -> ", " true"
break
end if
next m
if flag = 0 then print filenames$(n), " -> ", "false" : fi
next n
end
 
data ".zip", ".rar", ".7z", ".gz", ".archive", ".a##", ".tar.bz2"
data "MyData.a##", "MyData.tar.gz", "MyData.gzip", "MyData.7z.backup"
data "MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
 
=={{header|Batch File}}==
This solution does '''not''' contain support for dots in extension names.
<langsyntaxhighlight lang="dos">
@echo off
setlocal enabledelayedexpansion
Line 219 ⟶ 627:
shift
goto loop
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 229 ⟶ 637:
Filename: "MyData" | Extension: "" | FALSE
</pre>
 
 
=={{header|C}}==
Line 235 ⟶ 642:
===C: dots allowed ===
There is no magic in extensions: they are just trailing characters in names.
<langsyntaxhighlight lang="c">/*
* File extension is in extensions list (dots allowed).
*
Line 334 ⟶ 741:
getchar();
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 364 ⟶ 771:
According to this, an extension is whatever comes after the '''last''' dot. Dotless filename won't match anything.
 
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
#include <stdbool.h>
Line 433 ⟶ 840:
return 0;
}
</syntaxhighlight>
</lang>
 
=={{header|C++}}==
This solution allows extensions to contain dots.
<syntaxhighlight lang="cpp">#include <algorithm>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
 
bool endsWithIgnoreCase(const std::string& str, const std::string& suffix) {
const size_t n1 = str.length();
const size_t n2 = suffix.length();
if (n1 < n2)
return false;
return std::equal(str.begin() + (n1 - n2), str.end(), suffix.begin(),
[](char c1, char c2) {
return std::tolower(static_cast<unsigned char>(c1))
== std::tolower(static_cast<unsigned char>(c2));
});
}
 
bool filenameHasExtension(const std::string& filename,
const std::vector<std::string>& extensions) {
return std::any_of(extensions.begin(), extensions.end(),
[&filename](const std::string& extension) {
return endsWithIgnoreCase(filename, "." + extension);
});
}
 
void test(const std::string& filename,
const std::vector<std::string>& extensions) {
std::cout << std::setw(20) << std::left << filename
<< ": " << std::boolalpha
<< filenameHasExtension(filename, extensions) << '\n';
}
 
int main() {
const std::vector<std::string> extensions{"zip", "rar", "7z",
"gz", "archive", "A##", "tar.bz2"};
test("MyData.a##", extensions);
test("MyData.tar.Gz", extensions);
test("MyData.gzip", extensions);
test("MyData.7z.backup", extensions);
test("MyData...", extensions);
test("MyData", extensions);
test("MyData_v1.0.tar.bz2", extensions);
test("MyData_v1.0.bz2", extensions);
return 0;
}</syntaxhighlight>
 
{{out}}
<pre>
MyData.a## : true
MyData.tar.Gz : true
MyData.gzip : false
MyData.7z.backup : false
MyData... : false
MyData : false
MyData_v1.0.tar.bz2 : true
MyData_v1.0.bz2 : false
</pre>
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">(defn matches-extension [ext s]
(re-find (re-pattern (str "\\." ext "$"))
(clojure.string/lower-case s)))
 
(defn matches-extension-list [ext-list s]
(some #(matches-extension % s) ext-list))</syntaxhighlight>
 
It is assumed that when extensions are "added to the system", they will be "normalized" to the expected (lower) case.
 
<syntaxhighlight lang="clojure">(defn normalize-extensions [ext-list]
(map clojure.string/lower-case ext-list))</syntaxhighlight>
 
{{out}}
<pre>
(def ext-list ["zip" "rar" "7z" "gz" "archive" "A##" "tar.bz2"])
 
(def exts (normalize-extensions ext-list))
 
(map (partial matches-extension-list exts)
["MyData.a##"
"MyData.tar.Gz"
"MyData.gzip"
"MyData.7z.backup"
"MyData..."
"MyData"
"MyData_v1.0.tar.bz2"
"MyData_v1.0.bz2"])
 
(".a##" ".gz" nil nil nil nil ".tar.bz2" nil)
</pre>
 
=={{header|D}}==
===Variant 1===
<syntaxhighlight lang="d">
<lang d>
import std.stdio;
import std.string;
Line 474 ⟶ 975:
 
 
</syntaxhighlight>
</lang>
 
{{out}}
Line 491 ⟶ 992:
 
===Variant 2===
<syntaxhighlight lang="d">
<lang d>
import std.stdio;
import std.string;
Line 529 ⟶ 1,030:
}
 
</syntaxhighlight>
</lang>
 
{{out}}
Line 544 ⟶ 1,045:
MyData_v1.0.bz2 : false
 
</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|D}}
<syntaxhighlight lang="delphi">
program File_extension_is_in_extensions_list;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils;
 
const
exts: TArray<string> = ['zip', 'rar', '7z', 'gz', 'archive', 'A##', 'tar.bz2'];
filenames: TArray<string> = ['MyData.a##', 'MyData.tar.Gz', 'MyData.gzip',
'MyData.7z.backup', 'MyData...', 'MyData', 'MyData_v1.0.tar.bz2', 'MyData_v1.0.bz2'];
 
begin
write('extensions: [');
for var ext in exts do
begin
write(ext, ' ');
end;
writeln(']'#10);
 
for var filename in filenames do
begin
var found := false;
for var ext in exts do
if (filename.toLower.endsWith('.' + ext.toLower)) then
begin
found := True;
Break;
end;
writeln(filename: 20, ' : ', found);
end;
 
readln;
end.</syntaxhighlight>
{{out}}
<pre>extensions: [zip rar 7z gz archive A## tar.bz2 ]
 
MyData.a## : TRUE
MyData.tar.Gz : TRUE
MyData.gzip : FALSE
MyData.7z.backup : FALSE
MyData... : FALSE
MyData : FALSE
MyData_v1.0.tar.bz2 : TRUE
MyData_v1.0.bz2 : FALSE</pre>
 
=={{header|EasyLang}}==
{{trans|BASIC256}}
<syntaxhighlight>
exts$[] = [ ".zip" ".rar" ".7z" ".gz" ".archive" ".a##" ".tar.bz2" ]
fnames$[] = [ "MyData.a##" "MyData.tar.gz" "MyData.gzip" "MyData.7z.backup" "MyData..." "MyData" "MyData_v1.0.tar.bz2" "MyData_v1.0.bz2" ]
for fn$ in fnames$[]
ext$ = ""
for ext$ in exts$[]
h = len ext$
if substr fn$ (len fn$ - h + 1) h = ext$
print fn$ & " -> " & ext$ & " -> true"
break 1
.
.
if ext$ = ""
print fn$ & " -> false"
.
.
</syntaxhighlight>
{{out}}
<pre>
MyData.a## -> .a## -> true
MyData.tar.gz -> .gz -> true
MyData.gzip -> false
MyData.7z.backup -> false
MyData... -> false
MyData -> false
MyData_v1.0.tar.bz2 -> .tar.bz2 -> true
MyData_v1.0.bz2 -> false
</pre>
 
=={{header|Factor}}==
This solution allows dots in file extensions.
<langsyntaxhighlight lang="factor">USING: formatting kernel qw sequences splitting unicode ;
IN: rosetta-code.file-extension-list
 
Line 565 ⟶ 1,146:
filenames [
dup extensions ext-in-list? "%19s %u\n" printf
] each</langsyntaxhighlight>
{{out}}
<pre>
Line 588 ⟶ 1,169:
Petty details include the list employing capitals only, as the match is to not distinguish capital from lower case letters, so in the usual way the candidate extension's text is converted to capitals. The list could be subjected to UPCASE, but it is bad form to damage what might be a constant, and one possibly in read-only storage at that. An internal working copy could be made which would then be fed to UPCASE, except that this would be a waste on every invocation. A further trick involves appending a period to the candidate text so that for example ".JP" becomes ".JP." - otherwise a ".JP" would be found in the sequence ".JPG" which would be wrong, so as a result, the list of texts must have a period appended to its last entry, otherwise it would not be findable. Again, this could be done internally, via <code>INDEX(LIST//".",EXT(1:L)//".")</code> at a run-time cost.
 
Some systems supply an UPCASE (or similar name) to convert text that hopefully would run faster than this example, which relies on searching for the position in a list of letters. A very common alternative is to calculate using character code numerical values, via something like<langsyntaxhighlight Fortranlang="fortran"> IT = ICHAR(TEXT(I:I)) - ICHAR("a") !More symbols precede "a" than "A".
IF (IT.GE.0 .AND. IT.LE.25) TEXT(I:I) = CHAR(IT + ICHAR("A")) !In a-z? Convert!</langsyntaxhighlight> except that this relies on the letters having contiguous character codes, and in EBCDIC they don't - other symbols are mixed in. (Honest!) Faster still would be to use the character code to index an array of 256 pre-computed values.
 
A final annoyance is the presence of trailing spaces because character variables are of fixed size and so must be made "surely long enough" for the longest expectation. This may not cause trouble on output as spaces look just as blank as blank space, but they may well cause trouble in the internal tests. Thus integer function LSTNB reports the last non-blank, and so a test text can be presented with no trailing spaces, as in TEST(I)(1:LSTNB(TEST(I))) or similar. With Fortran 2003, there is a facility for redefining the sizes of character variables on-the-fly so that this problem can be evaded.
 
The MODULE protocol is employed for the convenience of not having to respecify the type of the functions in every calling routine, and also to facilitate the collection of types of characters. Otherwise, prior to F90 there would have to be various COMMON statements, or routines would each simply respecify whatever character sets they needed.<langsyntaxhighlight Fortranlang="fortran"> MODULE TEXTGNASH !Some text inspection.
CHARACTER*10 DIGITS !Integer only.
CHARACTER*11 DDIGITS !With a full stop masquerading as a decimal point.
Line 729 ⟶ 1,310:
END DO !On to the next.
END
</syntaxhighlight>
</lang>
The previous results were when only "image" style files were approved. The approval is no longer so restrictive.
<pre>
Line 755 ⟶ 1,336:
=={{header|Go}}==
This allows extensions to include a dot and, in the case of success, displays the extension matched (ignoring case) in the list. In the case of failure, the actual (minimum) file extension is displayed.
<langsyntaxhighlight lang="go">package main
 
import (
Line 797 ⟶ 1,378:
fmt.Printf("%-20s => %-5t (extension = %s)\n", test, ok, ext)
}
}</langsyntaxhighlight>
 
{{out}}
Line 813 ⟶ 1,394:
MyData_v1.0.bz2 => false (extension = bz2)
</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
void local fn DoIt
CFArrayRef extensions = @[@"zip",@"rar",@"7z",@"gz",@"archive",@"A##"]
CFArrayRef filenames = @[@"MyData.a##",@"MyData.tar.Gz",@"MyData.gzip",@"MyData.7z.backup",@"MyData...",@"MyData"]
CFStringRef name
NSLogSetTabInterval( 130 )
for name in filenames
NSLog(@"%@\t",name)
if ( fn ArrayContainsObject( fn ArrayValueForKey( extensions, @"lowercaseString" ), lcase(fn StringPathExtension(name) ) ) )
NSLog(@"true")
else
NSLog(@"false")
end if
next
end fn
 
fn DoIt
 
HandleEvents
</syntaxhighlight>
 
=={{header|Haskell}}==
 
<langsyntaxhighlight Haskelllang="haskell">import Data.List
import qualified Data.Char as Ch
 
Line 823 ⟶ 1,429:
 
isExt :: String -> [String] -> Bool
isExt filename extensions = any (`elem` (tails . toLower $ filename)) $ map toLower extensions</langsyntaxhighlight>
 
The code defining isExt could be done point free:
<langsyntaxhighlight Haskelllang="haskell">isExt filename = any (`elem` (tails . toLower $ filename)) . map toLower</langsyntaxhighlight>
 
Overcoming the one-liner urge on behalf of being more comprehensible would give:
<langsyntaxhighlight Haskelllang="haskell">isExt filename extensions = any (`elem` allTails) lowerExtensions
where allTails = tails . toLower $ filename
lowerExtensions = map toLower extensions</langsyntaxhighlight>
 
Given definition handles composite extensions as well.
Line 837 ⟶ 1,443:
'''Testing:'''
 
<langsyntaxhighlight Haskelllang="haskell">main = mapM_ (\f -> putStr(f ++ "\t") >> print (f `isExt` extensions)) files
where
files = [ "MyData.a##"
Line 847 ⟶ 1,453:
, "MyData_v1.0.tar.bz2"
, "MyData_v1.0.bz2" ]
extensions = ["zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"]</langsyntaxhighlight>
{{Out}}
<pre>λ> main
Line 858 ⟶ 1,464:
MyData_v1.0.tar.bz2 True
MyData_v1.0.bz2 False</pre>
 
 
We can also express this directly in terms of the '''isSuffix''' function, taking care not to reproduce the small glitch in the draft above, which shows a false positive for '''zip''' in '''.gzip''' (see task description bullet 2).
 
<syntaxhighlight lang ="haskell">import Data.ListChar (find, isSuffixOftoLower)
import Data.List (find, isSuffixOf)
import Data.Maybe (fromMaybe)
import Data.Char (toLower)
 
----------- FILE EXTENSION IS IN EXTENSIONS LIST ---------
 
extensionFound :: [String] -> [String] -> Maybe String
extensionFound xs fp xs = find (`isSuffixOf` fp) ($ ('.' :) <$> xs) >>= Just
 
 
-- TESTS ------------------------- TESTS -------------------------
main :: IO ()
main = do
putStrLn $
let w = maximum $ length <$> files
fTable
(putStrLn . unlines) $
"Any matching extensions found:\n"
zipWith
id
(\fp mb -> rjust w ' ' fp ++ " -> " ++ fromMaybe "n/a" mb)
(fromMaybe files"n/a")
((`extensionFound` lcased extensions) <$> lcased files)
(lowerCased ["zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"]))
(lowerCased
[ "MyData.a##"
, "MyData.tar.Gz"
, "MyData.gzip"
, "MyData.7z.backup"
, "MyData..."
, "MyData"
, "MyData_v1.0.tar.bz2"
, "MyData_v1.0.bz2"
])
 
-- DATA --------------------------- STRINGS ------------------------
fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> String
extensions, files :: [String]
fTable s xShow fxShow f xs =
extensions = ["zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"]
unlines $
s : fmap (((<>) . rjust w ' ' . xShow) <*> ((" -> " <>) . fxShow . f)) xs
where
rjust n c = drop . length <*> (replicate n c <>)
w = maximum (length . xShow <$> xs)
 
lowerCased :: [String] -> [String]
files =
lowerCased = fmap (fmap toLower)</syntaxhighlight>
[ "MyData.a##"
{{Out}}
, "MyData.tar.Gz"
<pre>Any matching extensions found:
, "MyData.gzip"
, "MyData.7z.backup"
, "MyData..."
, "MyData"
, "MyData_v1.0.tar.bz2"
, "MyData_v1.0.bz2"
]
 
mydata.a## -> .a##
-- STRINGS ------------------------------------------------
rjust :: Int -> Char -> Stringmydata.tar.gz -> String.gz
mydata.gzip -> n/a
rjust n c = (drop . length) <*> (replicate n c ++)
mydata.7z.backup -> n/a
 
mydata... -> n/a
lcased :: [String] -> [String]
mydata -> n/a
lcased = fmap (fmap toLower)</lang>
mydata_v1.0.tar.bz2 -> .tar.bz2
{{Out}}
<pre> MyDatamydata_v1.0.a##bz2 -> .n/a##</pre>
MyData.tar.Gz -> .gz
MyData.gzip -> n/a
MyData.7z.backup -> n/a
MyData... -> n/a
MyData -> n/a
MyData_v1.0.tar.bz2 -> .tar.bz2
MyData_v1.0.bz2 -> n/a</pre>
 
=={{header|J}}==
 
'''Solution:'''
<langsyntaxhighlight lang="j">isSuffix=: -~&# = {:@I.@E.
isExt=: ('.'&,&.>@[ ([: +./ isSuffix&(tolower@>)/) boxopen@])</langsyntaxhighlight>
 
'''Usage:'''
<langsyntaxhighlight lang="j"> Exts=: <;._1 ' zip rar 7z gz archive A## tar.bz2'
TestFiles=: <;._1 ' MyData.a## MyData.tar.Gz MyData.gzip MyData.7z.backup MyData... MyData MyData_v1.0.tar.bz2 MyData_v1.0.bz2'
Exts isExt TestFiles
1 1 0 0 0 0 1 0</langsyntaxhighlight>
 
=={{header|Java}}==
Line 927 ⟶ 1,538:
 
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java5">import java.util.Arrays;
import java.util.Comparator;
 
Line 960 ⟶ 1,571:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>Extensions: [.txt, .gz, , .bat]
Line 974 ⟶ 1,585:
{{works with|Java|6+}}
This version is the same as the main version only replace the definition for <code>extIsIn</code> with:
<langsyntaxhighlight lang="java5">public static boolean extIsIn(String test, String... exts){
for(int i = 0; i < exts.length; i++){
exts[i] = exts[i].replaceAll("\\.", "");
}
return (new FileNameExtensionFilter("extension test", exts)).accept(new File(test));
}</langsyntaxhighlight>
It would be one line if not for the dot requirement. <code>FileNameExtensionFilter</code> requires that the extensions have no dots. It also requires that the extensions contain characters (i.e. not the empty string) so that test would need to be removed.
 
=={{header|JavaScript}}==
 
This solution may not be the most performant but works for most implementations. Allows for dotted extensions, as well.
 
'''NOTE''' String.endsWith() was introduced with ECMAScript 6 (ES6), so that is a minimum requirement of your JS processor
 
<syntaxhighlight lang="javascript">
function fileExtensionInExtensionsList(filename) {
let foundIt = false;
let filenameLC = filename.toLowerCase();
let extensions = ["zip", "rar", "7z", "gz", "archive", "A##" ,"tar.bz2"];
extensions.forEach(extension => {
if (filenameLC.endsWith("." + extension.toLowerCase())) { foundIt = true; }
} );
return foundIt;
}
 
// perform tests below
 
var fileNamesToTest = [
"MyData.a##"
,"MyData.tar.Gz"
,"MyData.gzip"
,"MyData.7z.backup"
,"MyData..."
,"MyData"
,"MyData_v1.0.tar.bz2"
,"MyData_v1.0.bz2"
];
 
fileNamesToTest.forEach(filename => {
console.log(filename + " -> " + fileExtensionInExtensionsList(filename));
});
</syntaxhighlight>
 
{{out}}
(from tests - function returns true or false)
<pre>
MyData.a## -> true
MyData.tar.Gz -> true
MyData.gzip -> false
MyData.7z.backup -> false
MyData... -> false
MyData -> false
MyData_v1.0.tar.bz2 -> true
MyData_v1.0.bz2 -> false
</pre>
 
=={{header|jq}}==
Line 987 ⟶ 1,646:
 
{{works with|jq|1.4}}
<langsyntaxhighlight lang="jq"># Input: filename
# Output: if the filename ends with one of the extensions (ignoring case), output that extension; else output null.
# Assume that the list of file extensions consists of lower-case strings, including a leading period.
Line 996 ⟶ 1,655:
| if list | index($ext) then $ext else null end
else null
end;</langsyntaxhighlight>
'''Examples:'''
<langsyntaxhighlight lang="jq">("c:", "txt", "text.txt", "text.TXT", "foo.c", "foo.C++", "document.pdf")
| has_extension([".txt", ".c"]) as $ext
| if $ext then "\(.) has extension \($ext)"
else "\"\(.)\" does not have an admissible file extension"
end</langsyntaxhighlight>
 
{{out}}
<langsyntaxhighlight lang="jq">$ jq -r -n -f File_extension_is_in_extensions_list.jq
"c:" does not have an admissible file extension
"txt" does not have an admissible file extension
Line 1,012 ⟶ 1,671:
foo.c has extension .c
"foo.C++" does not have an admissible file extension
"document.pdf" does not have an admissible file extension</langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">isext(filename, extensions) = any(x -> endswith(lowercase(filename), lowercase(x)), "." .* extensions)
 
# Test
Line 1,023 ⟶ 1,682:
for f in ["MyData.a##", "MyData.tar.Gz", "MyData.gzip", "MyData.7z.backup", "MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"]
@printf("%20s : %5s\n", f, isext(f, extensions))
end</langsyntaxhighlight>
 
{{out}}
Line 1,036 ⟶ 1,695:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1
 
/* implicitly allows for extensions containing dots */
Line 1,059 ⟶ 1,718:
println("${fileName.padEnd(19)} -> ${fileName.isFileExtensionListed(extensions)}")
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,074 ⟶ 1,733:
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">-- Data declarations
local extentions = {"zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"}
local testCases = {
Line 1,100 ⟶ 1,759:
for _, case in pairs(testCases) do
print(case .. ": " .. tostring(extMatch(extentions, case)))
end</langsyntaxhighlight>
{{out}}
<pre>MyData.a##: true
Line 1,110 ⟶ 1,769:
MyData_v1.0.tar.bz2: true
MyData_v1.0.bz2: false</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[CheckExtension]
CheckExtension[fn_String, e : {_String ..}] := StringMatchQ[ToLowerCase[FileExtension[fn]], Alternatives @@ ToLowerCase[e]]
exts = {"zip", "rar", "7z", "gz", "archive", "A##"};
CheckExtension["MyData.a##", exts]
CheckExtension["MyData.tar.gz", exts]
CheckExtension["MyData.gzip", exts]
CheckExtension["MyData.7z.backup", exts]
CheckExtension["MyData..", exts]
CheckExtension["MyData", exts]</syntaxhighlight>
{{out}}
<pre>True
True
False
False
False
False</pre>
 
=={{header|Nim}}==
===Task===
For the task, it is possible to use the “splitFile” procedure from the standard module “os” as it split the extension at the last dot.
 
To build the extension list, we can use a compile time function:
<syntaxhighlight lang="nim">import os, strutils
 
let fileNameList = ["MyData.a##", "MyData.tar.Gz", "MyData.gzip",
"MyData.7z.backup", "MyData...", "MyData"]
 
func buildExtensionList(extensions: varargs[string]): seq[string] {.compileTime.} =
for ext in extensions:
result.add('.' & ext.toLowerAscii())
 
const ExtList = buildExtensionList("zip", "rar", "7z", "gz", "archive", "A##")
 
for fileName in fileNameList:
echo fileName, " → ", fileName.splitFile().ext.toLowerAscii() in ExtList</syntaxhighlight>
 
Another way consists to use “mapIt” from standard module “sequtils”:
<syntaxhighlight lang="nim">import os, sequtils, strutils
 
let fileNameList = ["MyData.a##", "MyData.tar.Gz", "MyData.gzip",
"MyData.7z.backup", "MyData...", "MyData"]
 
const ExtList = mapIt(["zip", "rar", "7z", "gz", "archive", "A##"], '.' & it.toLowerAscii())
 
for fileName in fileNameList:
echo fileName, " → ", fileName.splitFile().ext.toLowerAscii() in ExtList</syntaxhighlight>
 
{{out}}
<pre>MyData.a## → true
MyData.tar.Gz → true
MyData.gzip → false
MyData.7z.backup → false
MyData... → false
MyData → false</pre>
 
===Extra task===
The “splitFile” procedure no longer works in this case. We have to use “endsWith” from the “strutils” module, which changes the logic:
 
<syntaxhighlight lang="nim">import strutils, sequtils
 
let fileNameList = ["MyData.a##", "MyData.tar.Gz", "MyData.gzip",
"MyData.7z.backup", "MyData...", "MyData",
"MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"]
 
const ExtList = mapIt(["zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"], '.' & it.toLowerAscii())
 
for fileName in fileNameList:
echo fileName, " → ", ExtList.anyIt(fileName.toLowerAscii().endsWith(it))</syntaxhighlight>
 
{{out}}
<pre>MyData.a## → true
MyData.tar.Gz → true
MyData.gzip → false
MyData.7z.backup → false
MyData... → false
MyData → false
MyData_v1.0.tar.bz2 → true
MyData_v1.0.bz2 → false</pre>
 
=={{header|Objeck}}==
<langsyntaxhighlight lang="objeck">
class FileExtension {
function : Main(args : String[]) ~ Nil {
Line 1,136 ⟶ 1,875:
IO.Console->Print(file)->PrintLine(" does not have an extension in the list");
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,154 ⟶ 1,893:
The examples were taken from the [[#AWK|AWK]] code.
 
<langsyntaxhighlight lang="parigp">lower(s)=
{
my(v=Vecsmall(s));
Line 1,176 ⟶ 1,915:
ext=["txt","gz","bat","c","c++","exe","pdf"];
filenames=["c:","txt","text.txt","text.TXT","test.tar.gz","test/test2.exe","test","foo.c","foo.C","foo.C++","foo.c#","foo.zkl","document.pdf"];
select(f -> checkExt(ext, f), filenames)</langsyntaxhighlight>
{{out}}
<pre>%1 = ["text.txt", "text.TXT", "test.tar.gz", "test/test2.exe", "foo.c", "foo.C", "foo.C++", "document.pdf"]</pre>
Line 1,184 ⟶ 1,923:
Does the extra credit requirement.
 
{{trans|Perl 6Raku}}
 
<langsyntaxhighlight lang="perl">sub check_extension {
my ($filename, @extensions) = @_;
my $extensions = join '|', map quotemeta, @extensions;
scalar $filename =~ / \. (?: $extensions ) $ /xi
}</langsyntaxhighlight>
 
Testing:
<langsyntaxhighlight lang="perl">my @extensions = ('zip', 'rar', '7z', 'gz', 'archive', 'A##', 'tar.bz2');
my @files= (
'MyData.a##', 'MyData.tar.Gz', 'MyData.gzip', 'MyData.7z.backup',
Line 1,200 ⟶ 1,939:
printf "%-19s - %s\n",
$_, check_extension($_, @extensions) ? 'true' : 'false'
for @files;</langsyntaxhighlight>
 
{{out}}
Line 1,214 ⟶ 1,953:
</pre>
 
=={{header|PHP}}==
This solution does support the extra credit in the task
 
<syntaxhighlight lang="php">
=={{header|Perl 6}}==
$allowed = ['zip', 'rar', '7z', 'gz', 'archive', 'A##', 'tar.bz2'];
$lc_allowed = array_map('strtolower', $allowed);
 
$tests = [
Does the extra credit requirement.
['MyData.a##',true],
['MyData.tar.Gz',true],
['MyData.gzip',false],
['MyData.7z.backup',false],
['MyData...',false],
['MyData',false],
['archive.tar.gz', true]
];
 
foreach ($tests as $test) {
<lang perl6>sub check-extension ($filename, *@extensions) {
$ext = pathinfo($test[0], PATHINFO_EXTENSION);
so $filename ~~ /:i '.' @extensions $/
if (in_array(strtolower($ext), $lc_allowed)) {
$result = 'true';
} else {
$result = 'false';
}
printf("%20s : %s \n", $test[0],$result);
}
</syntaxhighlight>
 
# Testing:
 
my @extensions = <zip rar 7z gz archive A## tar.bz2>;
my @files= <
MyData.a## MyData.tar.Gz MyData.gzip MyData.7z.backup MyData... MyData
MyData_v1.0.tar.bz2 MyData_v1.0.bz2
>;
say "{$_.fmt: '%-19s'} - {check-extension $_, @extensions}" for @files;</lang>
 
{{out}}
MyData.a## : true
<pre>
MyData.a## MyData.tar.Gz : -true True
MyData.gzip : false
MyData.tar.Gz - True
MyData.7z.backup : false
MyData.gzip - False
MyData.7z.backup . : -false False
MyData... - False MyData : false
archive.tar.gz : true
MyData - False
MyData_v1.0.tar.bz2 - True
MyData_v1.0.bz2 - False
</pre>
 
=={{header|Phix}}==
Note there is builtin, however get_file_extension("MyData_v1.0.tar.bz2") yields "bz2", since it scans right-to-left for the '.', and also it also yields "so" for "libglfw.so.3.1" (it saves the "1", and the "3", but when they are all-number it carries on scanning left and replaces if it finds another '.'). So to match the task requirements more precisely we shall write a custom version.
<lang Phix>constant extensions = lower({"zip","rar","7z","gz","archive","A##","tar.bz2"})
<!--<syntaxhighlight lang="phix">(phixonline)-->
 
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
global function get_known_extension(string filename)
<span style="color: #008080;">constant</span> <span style="color: #000000;">extensions</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"zip"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"7z"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gz"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"archive"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"A##"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tar.bz2"</span><span style="color: #0000FF;">})</span>
filename = get_file_name(filename)
for i=1 to length(filename) do
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">get_known_extension</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
if filename[i]='.' then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
string extension = lower(filename[i+1..$])
<span style="color: #008080;">if</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
if find(extension,extensions) then
<span style="color: #004080;">string</span> <span style="color: #000000;">extension</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$])</span>
return extension
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">extension</span><span style="color: #0000FF;">,</span><span style="color: #000000;">extensions</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #000000;">extension</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return ""
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #008000;">""</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant tests = {"MyData.a##",
"MyData.tar.Gz",
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"MyData.a##"</span><span style="color: #0000FF;">,</span>
"MyData.gzip",
<span style="color: #008000;">"MyData.7ztar.backupGz"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"MyData...gzip"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"MyData.7z.backup"</span><span style="color: #0000FF;">,</span>
<span style="MyData_v1color: #008000;">"MyData.0.tar.bz2"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"MyData"</span><span style="color: #0000FF;">,</span>
"MyData_v1.0.bz2"}
<span style="color: #008000;">"MyData_v1.0.tar.bz2"</span><span style="color: #0000FF;">,</span>
 
<span style="color: #008000;">"MyData_v1.0.bz2"</span><span style="color: #0000FF;">}</span>
for i=1 to length(tests) do
string ti = tests[i],
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
ext = get_known_extension(ti)
<span style="color: #004080;">string</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
printf(1,"%-20s %-10s %s\n",{ti,ext,{"true","false"}[2-(find(ext,extensions)!=0)]})
<span style="color: #000000;">ext</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_known_extension</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)</span>
end for</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-20s %-10s %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ext</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"true"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"false"</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-(</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ext</span><span style="color: #0000FF;">,</span><span style="color: #000000;">extensions</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,288 ⟶ 2,036:
=={{header|Python}}==
 
<syntaxhighlight lang="python">
<lang Python>
def isExt(fileName, extensions):
return True in map(fileName.lower().endswith, ("." + e.lower() for e in extensions))
</syntaxhighlight>
</lang>
 
and we could also enrich the return value to a Maybe option type, returning Nothing if no file extension match is found, or Just the particular extension, if a match is found:
 
<syntaxhighlight lang="python">'''Check for a specific set of file extensions'''
 
 
# extensionFound :: [Extension] -> FileName -> Maybe Extension
def extensionFound(xs):
'''Nothing if no matching extension is found,
or Just the extension (drawn from xs, and
a suffix of the filename, immediately following
a dot character).
'''
return lambda fn: find(fn.lower().endswith)(
['.' + x.lower() for x in xs]
)
 
 
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''Check filenames for a particular set of extensions.'''
 
# checkExtension :: FileName -> Maybe Extension
def checkExtension(fn):
return extensionFound([
'zip', 'rar', '7z', 'gz', 'archive', 'A##', 'tar.bz2'
])(fn)
 
print(
fTable(__doc__ + ':\n')(str)(str)(
compose(fromMaybe('n/a'))(checkExtension)
)([
'MyData.a##',
'MyData.tar.Gz',
'MyData.gzip',
'MyData.7z.backup',
'MyData...',
'MyData',
'MyData_v1.0.tar.bz2',
'MyData_v1.0.bz2'
])
)
 
 
# GENERIC -------------------------------------------------
 
# Just :: a -> Maybe a
def Just(x):
'''Constructor for an inhabited Maybe (option type) value.'''
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
 
 
# Nothing :: Maybe a
def Nothing():
'''Constructor for an empty Maybe (option type) value.'''
return {'type': 'Maybe', 'Nothing': True}
 
 
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Right to left function composition.'''
return lambda f: lambda x: g(f(x))
 
 
# find :: (a -> Bool) -> [a] -> Maybe a
def find(p):
'''Just the first element in the list that matches p,
or Nothing if no elements match.
'''
def go(xs):
for x in xs:
if p(x):
return Just(x)
return Nothing()
return lambda xs: go(xs)
 
 
# fromMaybe :: a -> Maybe a -> a
def fromMaybe(x):
'''The default value x if mb is Nothing,
or the value contained in mb.
'''
return lambda mb: x if (
mb.get('Nothing')
) else mb.get('Just')
 
 
# DISPLAY -------------------------------------------------
 
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function -> fx display function ->
f -> xs -> tabular string.
'''
def go(xShow, fxShow, f, xs):
ys = [xShow(x) for x in xs]
w = max(map(len, ys))
return s + '\n' + '\n'.join(map(
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
xs, ys
))
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
xShow, fxShow, f, xs
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>Check for a specific set of file extensions:
 
MyData.a## -> .a##
MyData.tar.Gz -> .gz
MyData.gzip -> n/a
MyData.7z.backup -> n/a
MyData... -> n/a
MyData -> n/a
MyData_v1.0.tar.bz2 -> .tar.bz2
MyData_v1.0.bz2 -> n/a</pre>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 1,326 ⟶ 2,196:
(for ((f (in-list filenames)))
(printf "~a ~a~%" (~a #:width 20 f) (file-extension-in-list? f extensions)))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,337 ⟶ 2,207:
MyData_v1.0.tar.bz2 #t
MyData_v1.0.bz2 #f
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
 
Does the extra credit requirement.
 
<syntaxhighlight lang="raku" line>sub check-extension ($filename, *@extensions) {
so $filename ~~ /:i '.' @extensions $/
}
 
# Testing:
 
my @extensions = <zip rar 7z gz archive A## tar.bz2>;
my @files= <
MyData.a## MyData.tar.Gz MyData.gzip MyData.7z.backup MyData... MyData
MyData_v1.0.tar.bz2 MyData_v1.0.bz2
>;
say "{$_.fmt: '%-19s'} - {check-extension $_, @extensions}" for @files;</syntaxhighlight>
 
{{out}}
<pre>
MyData.a## - True
MyData.tar.Gz - True
MyData.gzip - False
MyData.7z.backup - False
MyData... - False
MyData - False
MyData_v1.0.tar.bz2 - True
MyData_v1.0.bz2 - False
</pre>
 
=={{header|REXX}}==
This REXX version handles the extra credit requirement.
<langsyntaxhighlight lang="rexx">/*REXX programpgm displays if a filename has a known extension (as per a list of EXTsextensions). */
$= 'zip rar 7z gz archive A## tar.bz2'; upper $ /*a list of "allowable" file extensions*/
parse arg fn /*obtain optional argument from the CL.*/
@.= /*define the default for the @. array.*/
if fn\='' then @.1 = strip(fn) /*A filename specified? Then use it. */
else do; @.1 = "MyData.a##" /*No " " elseElse use list*/
@.2 = "MyData.tar.Gz"
@.3 = "MyData.gzip"
Line 1,355 ⟶ 2,255:
@.8 = "MyData_v1.0.bz2"
end
#= words($)
 
do j=1 while @.j\==''; @@= @.j; upper @@ /*traipse through @ listfile ofextension file exts.list*/
file=@.j; upper file do k=1 for # until right(@@, L)==x /*getSearch $ alist, filename;is andextension thenin uppercaselist? it*/
x= . || word($, k); L=length(x) /*construct the extension of the file. */
 
do k=1 for # until right(file, length(x) )==x /*Search $ list, is ext in list?*/
x=. || word($, k) /*construct the extension of the file. */
end /*k*/ /* [↓] display file, and a nay or yea.*/
say right(@.j, 40) ' ' right( word( "false true", 1 + (k<=#) ), 5)
 
end /*j*/ /*stick a fork in it, we're all done. */</syntaxhighlight>
say right(@.j, 40) ' ' right( word( "false true", 1 + (k<=#) ), 5)
end /*j*/ /*stick a fork in it, we're all done. */</lang>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 1,379 ⟶ 2,276:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : File extension is in extensions list
 
Line 1,400 ⟶ 2,297:
ok
next
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,414 ⟶ 2,311:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">def is_ext(filename, extensions)
if filename.respond_to?(:each)
filename.each do |fn|
Line 1,427 ⟶ 2,324:
end
end
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,440 ⟶ 2,337:
=={{header|Rust}}==
Does extra credit.
<langsyntaxhighlight Rustlang="rust">fn main() {
let exts = ["zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"];
let filenames = [
Line 1,464 ⟶ 2,361:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,481 ⟶ 2,378:
=={{header|Scala}}==
 
<langsyntaxhighlight Scalalang="scala"> def isExt(fileName: String, extensions: List[String]): Boolean = {
extensions.map { _.toLowerCase }.exists { fileName.toLowerCase endsWith "." + _ }
}
</syntaxhighlight>
</lang>
 
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">func check_extension(filename, extensions) {
filename ~~ Regex('\.(' + extensions.map { .escape }.join('|') + ')\z', :i)
}</langsyntaxhighlight>
 
Testing:
<langsyntaxhighlight lang="ruby">var extensions = ['zip', 'rar', '7z', 'gz', 'archive', 'A##', 'tar.bz2']
 
var files = [
Line 1,502 ⟶ 2,399:
for file in files {
printf("%-19s - %s\n", file, check_extension(file, extensions))
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,517 ⟶ 2,414:
=={{header|Tcl}}==
 
<langsyntaxhighlight lang="tcl">
 
# This example includes the extra credit.
Line 1,583 ⟶ 2,480:
}
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,594 ⟶ 2,491:
MyData_v1.0.tar.bz2 true
MyData_v1.0.bz2 false
</pre>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="Zig">
const (
extensions = [".zip", ".rar", ".7z", ".gz", ".archive", ".a##", ".tar.bz2"]
filenames = ["MyData.a##", "MyData.tar.gz", "MyData.gzip", "MyData.7z.backup",
"MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"]
)
 
fn main() {
outer:
for oidx, file in filenames {
for idx, extension in extensions {
if file.substr_ni(file.len - extension.len, file.len) == extension {
println("${filenames[oidx]} -> ${extensions[idx]} -> true")
continue outer
}
}
println("${filenames[oidx]} -> false")
}
}
</syntaxhighlight>
 
{{out}}
<pre>
MyData.a## -> .a## -> true
MyData.tar.gz -> .gz -> true
MyData.gzip -> false
MyData.7z.backup -> false
MyData... -> false
MyData -> false
MyData_v1.0.tar.bz2 -> .tar.bz2 -> true
MyData_v1.0.bz2 -> false
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-str}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./str" for Str
import "./fmt" for Fmt
 
var exts = ["zip", "rar", "7z", "gz", "archive", "A##", "tar.bz2"]
 
var tests = [
"MyData.a##", "MyData.tar.Gz", "MyData.gzip" , "MyData.7z.backup",
"MyData...", "MyData", "MyData_v1.0.tar.bz2", "MyData_v1.0.bz2"
]
 
var ucExts = exts.map { |e| "." + Str.upper(e) }
for (test in tests) {
var ucTest = Str.upper(test)
var hasExt = false
var i = 0
for (ext in ucExts) {
hasExt = ucTest.endsWith(ext)
if (hasExt) {
Fmt.print("$-20s $s (extension: $s)", test, hasExt, exts[i])
break
}
i = i + 1
}
if (!hasExt) Fmt.print("$-20s $-5s", test, hasExt)
}</syntaxhighlight>
 
{{out}}
<pre>
MyData.a## true (extension: A##)
MyData.tar.Gz true (extension: gz)
MyData.gzip false
MyData.7z.backup false
MyData... false
MyData false
MyData_v1.0.tar.bz2 true (extension: tar.bz2)
MyData_v1.0.bz2 false
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">string 0;
 
func ToUpper(C); \Convert character to upper case
int C;
return if C>=^a & C<=^z then C&$DF else C;
 
func HasExt(File, Ext); \Return 'true' if File has Ext(ension)
char File, Ext;
int I, J;
[I:= 0;
while File(I) # 0 do I:= I+1;
while File(I) # ^. and I > 0 do I:= I-1;
I:= I+1;
J:= 0;
loop [if ToUpper(File(I+J)) # ToUpper(Ext(J)) then return false;
if Ext(J) = 0 then return true;
J:= J+1;
];
];
 
int Exts, Ext, Files, Test;
[Exts:= ["zip", "rar", "7z", "gz", "archive", "A##"];
Files:= ["MyData.a##", "MyData.tar.Gz", "MyData.gzip" , "MyData.7z.backup",
"MyData...", "MyData" ];
for Test:= 0 to 5 do
[for Ext:= 0 to 5 do
[if HasExt(Files(Test), Exts(Ext)) then
[Text(0, " true : ");
Ext:= 100;
];
];
if Ext = 6 then Text(0, "false : ");
Text(0, Files(Test));
CrLf(0);
];
]</syntaxhighlight>
{{out}}
<pre>
true : MyData.a##
true : MyData.tar.Gz
false : MyData.gzip
false : MyData.7z.backup
false : MyData...
false : MyData
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn hasExtension(fnm){
var [const] extensions=T(".zip",".rar",".7z",".gz",".archive",".a##");
nm,ext:=File.splitFileName(fnm)[-2,*].apply("toLower");
Line 1,608 ⟶ 2,626:
"MyData...","MyData",
"MyData_v1.0.tAr.bz2","MyData_v1.0.bz2");
foreach nm in (nms){ println("%20s : %s".fmt(nm,hasExtension(nm))); }</langsyntaxhighlight>
{{out}}
<pre>
1,981

edits