Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Goal:

Create a program to find the smallest file in the current folder.

  • File size may be measured in bytes or characters.
  • If multiple files have the same size, you can either choose one or display all of them.
  • You can assume there will be at least one file in the folder, and no files will have a size of 0.
  • Assume that all files in the folder can be accessed by the language you're using.

  • Assume that there are no folders in the current directory.

Input:

The program should not take any input from the user, unless:

  • If your language doesn't have a "current folder", it may ask the user for a folder name/path.
  • If your language cannot directly access files on your computer, it may allow the user to upload files. (JavaScript, for example)

Output:

The name of the smallest file should be displayed.

  • Leading/trailing symbols are allowed, as long as it's clear which file has been chosen.
  • (Printing a list of all the files is against the rules).

Notes:

  • Standard Loopholes are not allowed.
  • You cannot modify/create/delete files in the folder to change the result.
  • This is ; shortest answer (in bytes) wins.
share|improve this question
    
Can we assume files can have a size of 0? – Easterly Irk yesterday
    
Also, what does "assume that all files in the folder can be accessed" mean? does that mean hidden files don't need to be shown? – Easterly Irk yesterday
    
What if there are multiple files of the same size? does any work? – Easterly Irk yesterday
2  
Can I assume there are no folders on the current folder? It makes all the difference if you have a language function that returns both files and folders instead of only files! – sergiol yesterday
1  
Not necessarily. You may assume that there are no directories inside the current directory is unambiguous and doesn't invalidate any answers. – Dennis yesterday

19 Answers 19

Bash + coreutils, 13 bytes

ls -Sar|sed q
share|improve this answer
    
Posted this as my own answer, but I think it's too similar to yours. ls -1Sa|tail -1 is 3 bytes shorter and has cleaner output. – orlp yesterday
    
@orlp thanks!.. – Easterly Irk yesterday
    
I don't think you need the '-1', pipe automatically puts one file per line. – G B yesterday
    
@EasterlyIrk I think GB is right. if ls detects output is to the terminal it will format the output into multiple columns. But if output is a pipe it will just do 1 per line. Compare ls vs ls|cat – Digital Trauma yesterday
    
Two bytes shorter: ls -Sar|sed q – Digital Trauma yesterday

Python 2 3, 94 76 74 54 bytes

-18 bytes thanks to @orlp
-2 bytes thanks to @Jonathan Allan
-20 bytes thanks to a change in challenge specs

from os import*
print(min(listdir(),key=path.getsize))
share|improve this answer
    
print min(filter(path.isfile,listdir(".")),key=path.getsize) is cleaner and substantially shorter. – orlp yesterday
    
Save two bytes moving to Python 3 since "." is the default. print(min(filter(path.isfile,listdir()),key=path.getsize)) – Jonathan Allan yesterday
    
Also I count 76 not 77. – Jonathan Allan yesterday
    
@JonathanAllan I measured the byte count count with wc which gave me 1 byte more – ovs yesterday
    
The extraneous byte would be due to a trailing newline, which is not required for Python. Additionally, since the challenge was updated to state that there are no subdirectories present, the whole filter bit is unnecesary. This also doesn't work in Python 3, since print is a function. The following would work, and be substantially shorter: print(min(listdir(),key=path.getsize)) – Mego yesterday

PowerShell, 30 bytes

(ls -file|sort length)[0].Name

Try it online!

ls is an alias for Get-ChildItem, with the -file parameter so we only get files. That's piped to sort-object with the length attribute, so the files are sorted by size. We index into that with the (...)[0] to get the first (i.e., smallest), and then take the .Name thereof. Output via implicit Write-Output happens at program completion.

share|improve this answer
2  
Can you not get rid of the -file since only files are in the current directory? – Mutantoe 23 hours ago

MATLAB / Octave, 52 48 bytes

d=dir;[~,n]=min([d.bytes]./~[d.isdir]);d(n).name

Explanation

This gets a directory listing of all files and folders in the current directory using dir. The output of dir is a struct containing the filename, whether it's a directory or not, the size (in bytes), etc.

We can then take an array of the sizes of each in bytes [d.bytes] and perform element-wise division with a boolean indicating whether it's a directory or not ~[d.isdir] which will yield Inf where it's a directory (division by zero) and the size in bytes otherwise (division by 1).

We find the index of the minimum of this array using the second output of min and use that to index into the initial struct and display the name with d(n).name

share|improve this answer
    
You should add disp(...) around the output to properly print it. Otherwise if for example there was a file called ans that is not the smallest in the folder the output wouldn't be clear as to which file is the smallest to anyone unfamiliar with MATLAB. – Tom Carpenter 19 hours ago
    
@TomCarpenter Hmmm I interpreted "Leading/trailing symbols are allowed, as long as it's clear which file has been chosen" to mean that the ans = is ok – Suever 19 hours ago
    
I've just realised MATLAB adds the implicit . (current folder) and .. (folder above), so cant remove the directory check it seems. Sorry about that. – Tom Carpenter 19 hours ago

Ruby, 61 40 38 bytes

Thanks G B

p Dir[?*,".?*"].min_by{|x|File.size x}
share|improve this answer
    
You can use ?. instead of Dir.pwd, and min_by{} to get the smallest file. Dir.foreach(?.).min_by{|x|File.size x} gets the same result in 38 bytes. – G B yesterday
    
@GB Thanks! – wat yesterday
    
It's a shame that "all" files the language can access must be looked at, because Dir[?*] is much shorter but doesn't include hidden Unix files like .bash_profile... – Value Ink yesterday
    
Maybe Dir[?*,".?*"] could work. I haven't tried. And it's shorter. – G B 19 hours ago

Mathematica, 35 bytes

FileNames[]~MinimalBy~FileByteCount

FileNames[] produces a list of names of all the files (and directories) in the current directory; ~MinimalBy~FileByteCount selects the name of the file whose byte count is smallest. FileByteCount throws a bunch of errors when it's applied to directories, but the errors don't derail the program.

share|improve this answer

Batch, 43 39 bytes

@dir/a-d/b/os|(set/pf=&call echo %%f%%)

Output includes a leading space for some reason, but fortunately that's allowed.

share|improve this answer
    
Oh, using /p like that, dang clever! – AdmBorkBork yesterday
    
Since the challenge allows for leading symbols, can you get rid of the nul and accept the space? – AdmBorkBork yesterday
    
@AdmBorkBork Ah, I hadn't noticed that was allowed, thanks! – Neil yesterday

Java 7, 149 bytes

String f(){String n="";long s=-1>>>1,p;for(java.io.File f:new java.io.File(".").listFiles())if((p=f.getTotalSpace())<s){n=f.getName();s=p;}return n;}

Try it online!

share|improve this answer
    
I think you want File::length not File::getTotalSpace – CAD97 3 hours ago
    
Untested Java 8: ()->java.utils.stream(new java.io.File(".").listFiles()).max((a,b)->a.length()-b.lengt‌​h).get().getName() for 104 bytes – CAD97 3 hours ago

Bash 15 14 13 bytes

ls -S|tail -1

-S sorts by size (descending),

-rreverses and tail -1 outputs the last file in the list.

@ Dennis Thanks for saving 1 byte @Dani_l Thanks for saving 1 byte.

share|improve this answer
    
That finds the largest file, no? – Dennis yesterday
    
Nevermind, I'm tired. You could use tail though instead of reversing, and -1 is a shorthand for -n1. – Dennis yesterday
    
@Dennis Updated – Abel Tom yesterday

SmileBASIC, 110 bytes (non-competing)

DIM F$[0]FILES"TXT:",F$FOR I=0TO LEN(F$)-1F$[I][0]="TXT:
S=LEN(LOAD(F$[I],0))IF!Z||S<Z THEN Z=S:B=I
NEXT?F$[B]

Only looks at TXT: files, since DAT: files cannot be loaded unless you already know their size, making it impossible to load a random one. SB doesn't support nested folders, so I don't need to deal with that.

share|improve this answer
    
How do you load a DAT: file? Could you brute-force every name/file size in the folder? – Pavel yesterday
    
Trying to load a 3-dimensional DAT: file into a 2-dimensional array (for example) will cause an error, so you can't brute force it. You just have to know the number of dimensions beforehand, which you normally would. – 12Me21 yesterday
    
Could you load a 2-d DAT: file into a 3-d array? Then you could create a maximum size array. And you can't catch errors in any way? – Pavel yesterday
    
Nope, that will cause a Type mismatch error. And there's no way to catch errors either. – 12Me21 yesterday

V, 12 bytes

:r!ls -S
kdH

Try it online!

This only works on Linux.

share|improve this answer

J, 21 bytes

>{.{.(/:2&{"1)1!:0'*'

Explanation

>{.{.(/:2&{"1)1!:0'*'
                  '*' Glob all files in current directory
              1!:0    Table of file metadata in that directory
        2&{"1         Get the file size of each
      /:              Sort the files by that
   {.                 Get the first row
 {.                   Get the first column
>                     Unbox
share|improve this answer

Perl 6,  33 32  31 bytes

'.'.IO.dir.grep(*.f).min(*.s).put

Try it

put '.'.IO.dir.min:{try .s//Inf}

Try it

put $*CWD.dir.min:{try .s//Inf}

Try it

Expanded:

put        # print with trailing newline
$*CWD.dir  # the list of files in the current directory
.min:{     # find the minimum by
  try .s   # the size
  //       # if it fails ( because it was a directory )
  Inf      # use infinity instead
}
share|improve this answer

BATCH File, 77 72 bytes

@FOR /F "tokens=*" %%G IN ('dir /a:-d /o:-s /b') DO @SET F=%%G
@ECHO %F%

There's no direct equivalent of head or tail in BATCH, at least to my knowledge, so here's a kludgy work-around. (with assistance from @Neil - thanks!)

The dir command, with /a:-d to exclude directories, /o:-s to sort in descending file size, and /b to output only the file names. We loop through those with FOR /F, setting the variable F to the file name each time. Finally, we output just the last one with ECHO %F%.

share|improve this answer
    
Your FOR variable needs two %s to work in a script. Otherwise, a few golfing tricks: 1. Don't use @ECHO OFF on short scripts, add a @ to each line and after DO. 2. Delete the space before DO. 3. The spaces and :s aren't needed in the dir command. – Neil yesterday
    
@Neil Ack, thanks. Sorry, pretty rusty since I've been doing PowerShell... Thanks! – AdmBorkBork yesterday

Scala, 52 bytes

Old version, 79 bytes

new java.io.File(".").listFiles.map(a=>a.getName->a.length)sortBy(_._2)apply(0)

Adjusted according to jaxad0127's advice. It is only 52 bytes now.

new java.io.File(".").listFiles.sortBy(_.length)head
share|improve this answer
    
Using head instead of apply(0) is shorter. Also, the toString method of File is fine, no need to call get name. – jaxad0127 4 hours ago

tcl, 76

set s Inf
lmap f [glob -type f *] {
if [file size $f]<$s {set n $f}}
puts $n

demo

share|improve this answer

Node.js (using walk), 114 bytes

Ignore newline:

require('walk').walk(__dirname).on('file',(r,s,n)=>
(m=s.size>m.size?m:s,n()),m=0).on('end',_=>console.log(m.name))

This invokes a walker that traverses through the current directory (__dirname) and for each file calls a function with its stat s and a function next n() that must be invoked to continue the traversal. Then at the end, it prints a filename with the minimum size in bytes found. s.size>m.size returns false when m.size is undefined, so after the first callback, m is equal to the first file found, and continues from there normally.

share|improve this answer

PHP, 84 bytes

$t=array_map(filesize,$g=array_filter(glob('*'),is_file));asort($t);echo$g[key($t)];

This is the best I could do. Maybe there is a better way I'm missing.

$t=array_map(              # visit each array element and...
    filesize,              # map each filename to its filesize...
    $g=array_filter(       # using an array of...
        glob('*'),         # all files and directories...
        is_file            # filtered by files...
    )                      # 
);                         # 
asort($t);                 # sort the array of filesizes, then...
echo$g[key($t)];           # print element from the array of files using the first key of the sorted array as an index
share|improve this answer

TI-Basic, 1 Byte

ClrDraw

This was the best I could do.

share|improve this answer
    
This doesn't output the smallest file and is thus invalid. – Kritixi Lithos 2 hours ago
    
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review – Kritixi Lithos 2 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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