Unix/ls: Difference between revisions
→{{header|AWK}}: readdir function |
→{{header|Racket}}: No need to sort files, better looking tests |
||
Line 265: | Line 265: | ||
<lang racket>#lang racket/base |
<lang racket>#lang racket/base |
||
(require racket/string racket/file) |
|||
;; Racket's `directory-list' produces a sorted list of files |
|||
⚫ | |||
(displayln |
(define (ls) (for-each displayln (directory-list))) |
||
(string-join |
|||
(sort (map path->string (directory-list)) string<?) |
|||
"\n"))) |
|||
;; Code to run when this file is running directly |
|||
(module+ main |
(module+ main |
||
(ls)) |
(ls)) |
||
(module+ test |
(module+ test |
||
(require tests/eli-tester) |
(require tests/eli-tester racket/port racket/file) |
||
(define (make-directory-tree) |
(define (make-directory-tree) |
||
(make-directory* "foo/bar") |
(make-directory* "foo/bar") |
||
(for ( |
(for ([f '("1" "2" "a" "b")]) |
||
(with-output-to-file (format "foo/bar/~a"f) |
(with-output-to-file (format "foo/bar/~a"f) #:exists 'replace newline))) |
||
#:exists 'replace newline))) |
|||
(make-directory-tree) |
(make-directory-tree) |
||
⚫ | |||
(test |
|||
(parameterize ( |
(parameterize ([current-directory dir]) (with-output-to-string ls))) |
||
(test (ls/str "foo") => "bar\n" |
|||
(ls/str "foo/bar") => "1\n2\na\nb\n"))</lang> |
|||
(with-output-to-string ls) => "1\n2\na\nb\n")))</lang> |
|||
Both tests pass. |
Both tests pass. |
Revision as of 18:52, 23 November 2014
You are encouraged to solve this task according to the task description, using any language you may know.
Write a program that will list everything in the current folder, similar to the Unix utility “ls” [1] (or the Windows terminal command “DIR”). The output must be sorted, but printing extended details and producing multi-column output is not required.
- Example output
For the list of paths:
/foo/bar /foo/bar/1 /foo/bar/2 /foo/bar/a /foo/bar/b
When the program is executed in `/foo`, it should print:
bar
and when the program is executed in `/foo/bar`, it should print:
1 2 a b
Ada
<lang Ada>with Ada.Text_IO, Ada.Directories, Ada.Containers.Indefinite_Vectors;
procedure Directory_List is
use Ada.Directories, Ada.Text_IO; Search: Search_Type; Found: Directory_Entry_Type; package SV is new Ada.Containers.Indefinite_Vectors(Natural, String); Result: SV.Vector; package Sorting is new SV.Generic_Sorting; use Sorting; function SName return String is (Simple_Name(Found));
begin
Start_Search(Search, Directory => ".", Pattern =>""); while More_Entries(Search) loop Get_Next_Entry(Search, Found); declare Name: String := Simple_Name(Found); begin if Name(Name'First) /= '.' then Result.Append(Name); end if; -- ingnore filenames beginning with "." end; end loop; -- now Result holds the entire directory in arbitrary order Sort(Result); -- nor Result holds the directory in proper order for I in Result.First_Index .. Result.Last_Index loop Put_Line(Result.Element(I)); end loop;
end Directory_List;</lang>
AWK
"BEGINFILE" is a gawk-extension
<lang AWK>
- syntax: GAWK -f UNIX_LS.AWK * | SORT
BEGINFILE {
printf("%s\n",FILENAME) nextfile
} END {
exit(0)
} </lang>
Sample commands and output under Windows 8:
REM create folders and files MKDIR c:\foo\bar CD /D c:\foo\bar GAWK "BEGIN{x=\"12ab\";for(i=1;i<=length(x);i++){print(i)>substr(x,i,1)}}" REM run test CD /D c:\foo GAWK -f UNIX_LS.AWK * | SORT bar CD /D c:\foo\bar GAWK -f UNIX_LS.AWK * | SORT 1 2 a b
The following will list files only no directories (Unix 'ls' does not directly support this feature):
gawk -lreaddir 'BEGIN { FS = "/" } { if($3=="f") {print $2} }' /
C
C does not have any os-independent way of reading a directory. The following uses readdir and should work on any Unix system. <lang C>
- include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <limits.h>
- include <sys/types.h>
- include <dirent.h>
- include <unistd.h>
int cmpstr(const void *a, const void *b) {
return strcmp(*(const char**)a, *(const char**)b);
}
int main(void) {
DIR *basedir; char path[PATH_MAX]; struct dirent *entry; char **dirnames; int diralloc = 128; int dirsize = 0; if (!(dirnames = malloc(diralloc * sizeof(char*)))) { perror("malloc error:"); return 1; }
if (!getcwd(path, PATH_MAX)) { perror("getcwd error:"); return 1; }
if (!(basedir = opendir(path))) { perror("opendir error:"); return 1; }
while ((entry = readdir(basedir))) { if (dirsize >= diralloc) { diralloc *= 2; if (!(dirnames = realloc(dirnames, diralloc * sizeof(char*)))) { perror("realloc error:"); return 1; } } dirnames[dirsize++] = strdup(entry->d_name); }
qsort(dirnames, dirsize, sizeof(char*), cmpstr);
int i; for (i = 0; i < dirsize; ++i) { if (dirnames[i][0] != '.') { printf("%s\n", dirnames[i]); } }
for (i = 0; i < dirsize; ++i) free(dirnames[i]); free(dirnames); closedir(basedir); return 0;
} </lang>
Clojure
<lang clojure>(def files (sort (filter #(= "." (.getParent %)) (file-seq (clojure.java.io/file ".")))))
(doseq [n files] (println (.getName n)))</lang>
D
<lang d>void main() {
import std.stdio, std.file, std.path;
foreach (const string path; dirEntries(getcwd, SpanMode.shallow)) path.baseName.writeln;
}</lang>
Go
<lang go>package main
import ( "fmt" "log" "os" "sort" )
func main() { f, err := os.Open(".") if err != nil { log.Fatal(err) } files, err := f.Readdirnames(0) f.Close() if err != nil { log.Fatal(err) } sort.Strings(files) for _, n := range files { fmt.Println(n) } }</lang>
Haskell
<lang haskell>#!/usr/bin/env runghc
import Control.Monad import Data.List import System.Directory
main = do
files <- getDirectoryContents "." mapM_ putStrLn $ sort $ filter (\x -> head x /= '.') files</lang>
J
<lang J> dir '*' NB. includes properties
> 1 dir '*' NB. plain filename as per task</lang>
Mathematica
<lang Mathematica>Column[FileNames[]]</lang>
OCaml
<lang ocaml>let () =
Array.iter print_endline ( Sys.readdir Sys.argv.(1) )</lang>
- Output:
$ cd /foo/bar $ ocaml ls.ml 1 2 a b
PARI/GP
GP doesn't have this capability so we can either use the shell or PARI. For the latter see C; for the former: <lang parigp>system("dir/b/on")</lang> in DOS/Windows or <lang parigp>system("ls")</lang> in *nix.
Perl 6
There is a dir builtin command which returns a list of IO::Path objects. We stringify them all with a hyperoperator before sorting the strings.
<lang perl6>.say for sort ~«dir</lang>
Python
<lang python>>>> import os >>> print('\n'.join(sorted(os.listdir('.')))) DLLs Doc LICENSE.txt Lib NEWS.txt README.txt Scripts Tools include libs python.exe pythonw.exe tcl >>> </lang>
Racket
Ooh... warning... if you run the test
module (either with DrRacket with the test module automatically running, or with raco test ls.rkt
, then the example directory tree is built but not torn down.
<lang racket>#lang racket/base
- Racket's `directory-list' produces a sorted list of files
(define (ls) (for-each displayln (directory-list)))
- Code to run when this file is running directly
(module+ main
(ls))
(module+ test
(require tests/eli-tester racket/port racket/file) (define (make-directory-tree) (make-directory* "foo/bar") (for ([f '("1" "2" "a" "b")]) (with-output-to-file (format "foo/bar/~a"f) #:exists 'replace newline))) (make-directory-tree) (define (ls/str dir) (parameterize ([current-directory dir]) (with-output-to-string ls))) (test (ls/str "foo") => "bar\n" (ls/str "foo/bar") => "1\n2\na\nb\n"))</lang>
Both tests pass.
REXX
The following program works under Windows and used the Windows DIR command to list a bare-bones sorted list. <lang rexx>/*REXX program lists contents of current folder (ala mode UNIX's LS). */ 'DIR /b /oN' /*use Windows DIR: sorts & lists.*/
/*stick a fork in it, we're done.*/</lang>
Ruby
<lang ruby> Dir.foreach("./"){|n| puts n} </lang> This will output all files including hidden ones e.g. '.' and '..'.
Rust
<lang rust>use std::os; use std::io::fs;
fn main() { let cwd = os::getcwd(); let info = fs::readdir(&cwd).unwrap();
let mut filenames = Vec::new(); for entry in info.iter() { filenames.push(entry.filename_str().unwrap()); }
filenames.sort(); for filename in filenames.iter() { println!("{}", filename); } }</lang>
Sidef
Explicit, by opening the current working directory: <lang ruby>var content = []; Dir.cwd.open.each { |file|
file ~~ < . .. > && next; content.append(file);
};
content.sort.each { |file|
say file;
};</lang>
Implicit, by using the String.glob method: <lang ruby>'*'.glob.each { |file|
say file;
};</lang>
Tcl
<lang tcl>puts [join [lsort [glob -nocomplain *]] "\n"]</lang>
zkl
<lang zkl>File.glob("*").sort()</lang> Lists all files and directories in the current directory. If you only want a list of files: <lang zkl>File.glob("*",0x8).sort()</lang>
- Output:
L("README","superball","testThemAll.log","zkl.exe","zkl_tests.zip","zkl_vm_src.zip")
The glob method uses Unix shell wild cards.
The globular method recurses down through the directories. It can send results to objects, functions, methods, threads, etc, etc. To get a sorted list of all the directories under the "Src" directory: <lang zkl>File.globular("Src",*,True,0x10,List).sort().concat("\n")</lang>
- Output:
Src/Compiler/ Src/Misc/ Src/Test/ Src/Time/ Src/Utils/ Src/ZenKinetic/ Src/ZenKinetic/Frame_O_Matic/ Src/ZenKinetic/GBalls/ Src/ZenKinetic/Twist and Draw/ Src/ZenKinetic/ZEd