# .fsx vs .fs

# Understanding F# Files: `.fsx` vs `.fs` (with a Practical `stat.fsx` Example)

When learning F#, one of the first confusions beginners face is the difference between `.fsx` files (F# scripts) and `.fs` files (source files part of a project). Understanding this distinction is essential for writing efficient scripts, experimenting, or developing full-fledged applications.

---

## 1️⃣ `.fsx` — F# Script Files

`.fsx` files are **interactive scripts**, designed for **quick prototyping, automation, or teaching**. They are **executed directly by F# Interactive (FSI)** and **do not require compilation**.

### Key Features:

* **Execution:** Interpreted top-to-bottom via `dotnet fsi script.fsx`
    
* **EntryPoint:** Optional
    
* **References:** Can include packages or DLLs inline using `#r "..."`
    
* **Order Matters:** Code runs sequentially as written
    

**Use Case:** Quick experiments, file processing scripts, teaching examples.

---

### Example: `stat.fsx` — Show File/Directory Metadata

This script demonstrates **how to get size, last modified time, and permissions** for files and directories:

```fsharp
open System
open System.IO

/// Show metadata for a file or directory
let showStat path =
    if File.Exists path then
        let f = FileInfo path
        printfn "File: %s" f.FullName
        
    elif Directory.Exists path then
        let d = DirectoryInfo path
       
        printfn "Last modified: %s" (d.LastWriteTime.ToString())
    else
        printfn "stat: cannot stat '%s': No such file or directory" path

/// Get command-line argument from FSI
let args =
    if fsi.CommandLineArgs.Length > 1 then fsi.CommandLineArgs.[1..] else [||]

match args with
| [| path |] -> showStat path
| _ -> printfn "Usage: dotnet fsi stat.fsx <file-or-directory>"
```

**Run the script:**

```bash
dotnet fsi stat.fsx /path/to/file
```

This is perfect for **learning file I/O in F#** and demonstrates a practical use of `.fsx` scripts.

---

## 2️⃣ `.fs` — F# Source Files

`.fs` files are **part of a formal F# project**. They are **compiled** using the project file (`.fsproj`) and produce a DLL or EXE.

### Key Features:

* **Execution:** Compiled → run via `dotnet run` or referenced as a library
    
* **EntryPoint:** `[<EntryPoint>]` required for console apps
    
* **References:** Managed via `.fsproj` or NuGet
    
* **Use Case:** Multi-file applications, production software, libraries
    

**Example:** A console application, library, or large F# service.

---

## 3️⃣ `.fsx` vs `.fs` — Quick Comparison

| Feature | `.fsx` | `.fs` |
| --- | --- | --- |
| Execution | `dotnet fsi script.fsx` | `dotnet build` → `dotnet run` |
| Build required | ❌ No | ✅ Yes |
| EntryPoint | Optional | Required for console apps |
| Multi-file | Less common | Standard |
| References | Inline (`#r`) | Project-managed (`.fsproj`) |

---

## 4️⃣ When to Use Which

* **Use** `.fsx` for **learning, scripting, automation, or experiments**.
    
* **Use** `.fs` when building **production applications, libraries, or multi-file projects**.
    

The `stat.fsx` example is a perfect demonstration of `.fsx` usage: a **self-contained script** that interacts with the filesystem, useful for both **learning F# I/O** and **practical scripting**.

---

💡 **Pro Tip:** Start small with `.fsx` scripts to prototype functionality quickly. Once your logic stabilizes and your code grows, migrate it into a `.fsproj` project with `.fs` files for a more maintainable and production-ready structure.

---
