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 11 hours ago
    
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 11 hours ago
    
What if there are multiple files of the same size? does any work? – Easterly Irk 11 hours ago
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 7 hours ago
1  
Not necessarily. You may assume that there are no directories inside the current directory is unambiguous and doesn't invalidate any answers. – Dennis 5 hours ago

17 Answers 17

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 11 hours ago
    
@orlp thanks!.. – Easterly Irk 11 hours ago
    
I don't think you need the '-1', pipe automatically puts one file per line. – G B 11 hours ago
    
@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 11 hours ago
    
Two bytes shorter: ls -Sar|sed q – Digital Trauma 11 hours ago

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

Ruby, 61 40 bytes

Thanks G B

p Dir.foreach(?.).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 11 hours ago
    
@GB Thanks! – wat 10 hours ago
    
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 7 hours ago

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 11 hours ago
    
Save two bytes moving to Python 3 since "." is the default. print(min(filter(path.isfile,listdir()),key=path.getsize)) – Jonathan Allan 10 hours ago
    
Also I count 76 not 77. – Jonathan Allan 10 hours ago
    
@JonathanAllan I measured the byte count count with wc which gave me 1 byte more – ovs 10 hours ago
    
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 4 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

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

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 10 hours ago
    
Since the challenge allows for leading symbols, can you get rid of the nul and accept the space? – AdmBorkBork 10 hours ago
    
@AdmBorkBork Ah, I hadn't noticed that was allowed, thanks! – Neil 9 hours ago

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

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 10 hours ago
    
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 10 hours ago
    
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 10 hours ago
    
Nope, that will cause a Type mismatch error. And there's no way to catch errors either. – 12Me21 10 hours ago

V, 12 bytes

:r!ls -S
kdH

Try it online!

This only works on Linux.

share|improve this answer

Bash 15 14 bytes

ls -S|tail -n1

-S sorts by size (descending),

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

@ Dennis thanks for saving 1 byte

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

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 11 hours ago
    
@Neil Ack, thanks. Sorry, pretty rusty since I've been doing PowerShell... Thanks! – AdmBorkBork 11 hours ago

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

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

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.