To create a text file from the Linux command line, use touch filename.txt for an empty file, nano filename.txt to create and edit interactively, or echo "content" > filename.txt to create a file with content in one command. To edit an existing file, open it with a terminal editor like nano filename.txt or vim filename.txt. For appending content without opening an editor, use echo "more text" >> filename.txt (the >> appends rather than overwrites).
Files Without a Graphical Interface
Working entirely from the command line means creating and modifying text files without ever opening a graphical text editor window. This might sound limiting, but Linux’s command line provides an extensive toolkit for file creation and editing — from the simplest possible approach (an empty file with touch) to full-featured interactive editing (nano, vim) to programmatic content generation (echo, printf, redirection, heredocs) that is often faster and more scriptable than opening a graphical editor at all.
Understanding these techniques matters for more than convenience. Server administration happens almost entirely over SSH connections with no graphical interface available. Scripts that configure systems need to generate files programmatically rather than requiring someone to type content into an editor. Quick edits to configuration files are faster with a one-line command than launching an editor for a single-line change. And working comfortably in a terminal-only environment (a minimal server, a container, a recovery shell) requires knowing these techniques by heart.
This article covers every practical method for creating and editing text files from the Linux terminal: creating empty files, writing content with echo and printf, using redirection operators, heredocs for multi-line content, terminal editors for interactive editing, and practical techniques that combine these approaches for real-world tasks.
Creating Empty Files: touch
The simplest file creation tool, touch, creates an empty file if it does not exist:
$ touch newfile.txt
$ ls -la newfile.txt
-rw-r--r-- 1 sarah sarah 0 Feb 18 11:00 newfile.txt
The file exists with zero bytes of content.
touch’s Real Purpose: Updating Timestamps
touch‘s actual designed purpose is updating a file’s timestamp — its name is short for “touching” the file to mark it as recently accessed/modified, without changing its content:
$ touch existingfile.txt # Updates modification time to now, content unchanged
This is useful in build systems and scripts that check file modification times to decide whether to rebuild something.
Creating Multiple Files at Once
$ touch file1.txt file2.txt file3.txt
$ touch report_{jan,feb,mar}.txt # Creates report_jan.txt, report_feb.txt, report_mar.txt
Creating Files with Specific Timestamps
$ touch -t 202602180930 old_file.txt # Sets timestamp to Feb 18, 2026, 09:30
$ touch -d "2026-01-01" newyear.txt # Sets timestamp using a date string
$ touch -r reference.txt target.txt # Sets target.txt's timestamp to match reference.txt
Writing Content Directly: echo and printf
echo: Simple Single-Line Content
$ echo "Hello, World!" > greeting.txt
$ cat greeting.txt
Hello, World!
The > operator redirects echo‘s output into the file, creating it if it does not exist, or overwriting it completely if it does.
Appending instead of overwriting:
$ echo "Second line" >> greeting.txt
$ cat greeting.txt
Hello, World!
Second line
The >> operator appends to the end of the file rather than replacing its contents.
Writing Multiple Lines with echo
$ echo -e "Line 1\nLine 2\nLine 3" > multiline.txt
$ cat multiline.txt
Line 1
Line 2
Line 3
The -e flag enables interpretation of backslash escapes like \n (newline), \t (tab).
printf: More Precise Formatting
printf offers more control over formatting than echo, especially useful in scripts:
$ printf "Name: %s\nAge: %d\n" "Sarah" 30 > info.txt
$ cat info.txt
Name: Sarah
Age: 30
printf does not automatically add a trailing newline (unlike echo), so you must include \n explicitly where needed.
Building a File Incrementally
$ echo "# Project TODO" > TODO.txt
$ echo "" >> TODO.txt
$ echo "- Fix login bug" >> TODO.txt
$ echo "- Update documentation" >> TODO.txt
$ echo "- Deploy to production" >> TODO.txt
$ cat TODO.txt
# Project TODO
- Fix login bug
- Update documentation
- Deploy to production
Heredocs: Writing Multi-Line Content Cleanly
For writing substantial multi-line content without repeated echo commands, a heredoc (here document) is the cleanest approach:
$ cat > config.txt << EOF
server {
listen 80;
server_name example.com;
root /var/www/html;
}
EOF
This creates config.txt with exactly the content between << EOF and the matching EOF on its own line. The delimiter word (EOF is conventional but any word works) marks where the content ends.
Appending with Heredocs
$ cat >> config.txt << EOF
location /api {
proxy_pass http://localhost:3000;
}
EOF
Heredocs with Variable Expansion
By default, heredocs expand shell variables:
$ NAME="Sarah"
$ cat > greeting.txt << EOF
Hello, $NAME!
Today is $(date +%A).
EOF
$ cat greeting.txt
Hello, Sarah!
Today is Wednesday.
Preventing variable expansion — quote the delimiter to treat the content as fully literal:
$ cat > script_template.sh << 'EOF'
#!/bin/bash
echo "The variable $HOME will NOT be expanded here"
EOF
$ cat script_template.sh
#!/bin/bash
echo "The variable $HOME will NOT be expanded here"
This is essential when writing scripts or configuration files that themselves contain $variable syntax that should be preserved literally, not expanded by your current shell.
Heredocs for Complex Configuration Files
Heredocs excel at generating configuration files in scripts:
#!/bin/bash
# Generate an nginx virtual host configuration
cat > /etc/nginx/sites-available/mysite.conf << EOF
server {
listen 80;
server_name ${DOMAIN};
root ${WEBROOT};
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
EOF
Note the escaped \$uri — this prevents the shell from trying to expand $uri as a shell variable (it does not exist in the script’s context; it is meant for nginx to interpret), while ${DOMAIN} and ${WEBROOT} remain unescaped so the script’s own variables ARE expanded.
heredoc with sudo (Writing to Root-Owned Files)
A common gotcha: sudo cat > /etc/protected_file << EOF does not work as expected, because the redirection (>) happens in your unprivileged shell, not under sudo. The correct pattern:
$ sudo tee /etc/protected_file << EOF > /dev/null
line 1
line 2
EOF
tee runs with sudo privileges and writes to the file, while the heredoc content still comes from your shell.
The tee Command: Writing While Viewing
tee writes its input both to a file and to standard output — useful for writing to a file while still seeing the content, and essential for writing to files requiring elevated privileges:
$ echo "New configuration line" | sudo tee -a /etc/somefile.conf
New configuration line
The -a (append) flag appends rather than overwrites. Without -a, tee overwrites the file (like >).
Writing to multiple files simultaneously:
$ echo "shared content" | tee file1.txt file2.txt file3.txt
Combining with sudo for privileged file editing without opening an editor:
$ echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
Terminal Text Editors: Interactive Editing
For substantial editing, an interactive terminal editor is more practical than constructing content through echo or heredocs.
nano: The Beginner-Friendly Editor
$ nano newfile.txt
Type content directly. Save with Ctrl+O, confirm filename with Enter, exit with Ctrl+X. See the dedicated nano article in this series for complete coverage of nano’s features.
vim/vi: The Powerful Modal Editor
$ vim newfile.txt
Vim starts in “Normal mode” where keys are commands, not text input. Press i to enter Insert mode and type content. Press Escape to return to Normal mode. Save and exit with :wq followed by Enter (or just save with :w, or quit without saving with :q!).
Absolute minimum vim survival commands:
i # Enter insert mode (start typing)
Escape # Return to normal mode
:w # Save (write)
:q # Quit
:wq # Save and quit
:q! # Quit without saving (force)
Choosing an Editor for Quick Edits
For a single quick edit to an existing file, nano is generally faster to use correctly for those unfamiliar with vim’s modal editing. For repeated editing tasks, learning vim’s efficiency pays dividends over time.
Reading and Verifying File Content
After creating or editing a file, verify its content:
$ cat filename.txt # Print entire content
$ less filename.txt # Page through content (q to quit)
$ head filename.txt # First 10 lines
$ head -n 5 filename.txt # First 5 lines
$ tail filename.txt # Last 10 lines
$ tail -f logfile.txt # Follow (watch new lines as they are added)
$ wc -l filename.txt # Count lines
$ file filename.txt # Identify the file type
Copying and Renaming Files from the Command Line
While not strictly “creating” files, these related operations are part of the same workflow:
$ cp original.txt copy.txt # Copy a file
$ cp -i original.txt copy.txt # Copy with confirmation before overwrite
$ mv oldname.txt newname.txt # Rename (or move)
$ cp -r sourcedir/ destdir/ # Copy a directory recursively
Creating a file based on a template:
$ cp /etc/skel/.bashrc ~/new_config_starting_point
Practical Techniques for Common Tasks
Creating a Script File
$ cat > backup.sh << 'EOF'
#!/bin/bash
# Simple backup script
SOURCE="$HOME/Documents"
DEST="/backup/documents_$(date +%Y%m%d).tar.gz"
tar -czf "$DEST" "$SOURCE"
echo "Backup created: $DEST"
EOF
$ chmod +x backup.sh
$ ./backup.sh
Note the single-quoted 'EOF' — this prevents $HOME and $(date...) from being expanded when the heredoc is written, so they remain literal in the script and are correctly expanded later when the script actually runs.
Creating a Configuration File with Variable Substitution
#!/bin/bash
APP_NAME="myapp"
APP_PORT="8080"
cat > "/etc/${APP_NAME}/config.ini" << EOF
[server]
name = ${APP_NAME}
port = ${APP_PORT}
started = $(date)
EOF
Here the unquoted EOF allows variable expansion so the actual values are written into the file.
Appending a Line Only If It Does Not Already Exist
Avoiding duplicate entries when adding configuration lines:
$ grep -qxF "127.0.0.1 myapp.local" /etc/hosts || echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
grep -qxF checks quietly (-q) for an exact (-x) fixed-string (-F) match; if not found, the || triggers the append.
Creating an Empty File with Specific Permissions
$ install -m 600 /dev/null secretfile.txt
$ ls -la secretfile.txt
-rw------- 1 sarah sarah 0 Feb 18 11:30 secretfile.txt
install creates the file with the specified mode in one step, rather than touch followed by chmod.
Quickly Editing a Config File Value
Changing a single line in a config file without opening an editor, using sed:
$ sed -i 's/^port = .*/port = 9090/' config.ini
This finds any line starting with port = and replaces it entirely — useful for scripted configuration changes.
Creating a File with Today’s Date in the Name
$ touch "report_$(date +%Y-%m-%d).txt"
$ ls report_*.txt
report_2026-02-18.txt
Combining Multiple Files Into One
$ cat file1.txt file2.txt file3.txt > combined.txt
$ cat *.txt > all_combined.txt
Understanding Redirection Operators
A quick reference for the redirection operators used throughout this article:
| Operator | Effect |
|---|---|
> |
Redirect stdout to file, overwriting existing content |
>> |
Redirect stdout to file, appending to existing content |
< |
Redirect file content as stdin to a command |
2> |
Redirect stderr to file |
2>> |
Append stderr to file |
&> |
Redirect both stdout and stderr to file |
2>&1 |
Redirect stderr to the same place as stdout |
<< |
Heredoc: multi-line input until delimiter |
<<< |
Herestring: single string as input |
Herestring example:
$ grep "pattern" <<< "some text with pattern in it"
some text with pattern in it
Safety Practices When Creating and Editing Files
Always Confirm Before Overwriting Important Files
The > operator overwrites silently with no confirmation. Before running a command with > against an important file, double-check the filename:
$ echo "test" > important_config.txt # DANGER if this file existed with content!
Consider using noclobber to prevent accidental overwrites in your interactive shell:
# Add to ~/.bashrc
set -o noclobber
With noclobber enabled, > refuses to overwrite an existing file (reporting an error), while >| explicitly forces the overwrite when you really want it.
Back Up Before Editing System Files
$ sudo cp /etc/important.conf /etc/important.conf.bak
$ sudo nano /etc/important.conf
Use Version Control for Important Scripts
For scripts and configuration files you edit repeatedly, consider tracking them in git:
$ cd ~/scripts
$ git init
$ git add backup.sh
$ git commit -m "Initial backup script"
This gives you a complete history of changes and the ability to revert if an edit introduces a problem.
Quick Reference: File Creation and Editing Commands
| Task | Command |
|---|---|
| Create empty file | touch filename.txt |
| Create with single line | echo "content" > filename.txt |
| Append a line | echo "content" >> filename.txt |
| Create with multiple lines | cat > filename.txt << EOF … EOF |
| Append multiple lines | cat >> filename.txt << EOF … EOF |
| Write without variable expansion | cat > file << 'EOF' … EOF |
| Edit interactively (beginner) | nano filename.txt |
| Edit interactively (advanced) | vim filename.txt |
| Write to privileged file | echo "content" | sudo tee -a /path/file |
| View file content | cat filename.txt |
| Page through content | less filename.txt |
| Copy a file | cp source.txt dest.txt |
| Rename a file | mv old.txt new.txt |
| Combine files | cat file1.txt file2.txt > combined.txt |
| Replace text in file | sed -i 's/old/new/' filename.txt |
| Create with permissions set | install -m 600 /dev/null filename.txt |
Conclusion: The Terminal as a Complete Editing Environment
Creating and editing text files from the command line is not a limited fallback for when a graphical editor is unavailable — it is a complete, often more efficient way of working with text. touch for instant empty files, echo and printf for quick single-line content, heredocs for clean multi-line generation, tee for privileged writes, and nano or vim for interactive editing together cover every scenario you will encounter.
The techniques compound in scripts: a deployment script that generates configuration files with heredocs, a setup script that appends to /etc/hosts only if the entry does not already exist, a backup script that creates dated filenames automatically. This is the real power of command-line file creation — it is not just an alternative to graphical editing, it is programmable, repeatable, and scriptable in ways that clicking through a graphical editor never can be.
Master these techniques and working entirely within a terminal — whether by choice or because you are managing a remote server with no graphical interface — becomes not a limitation but simply another complete way of getting things done.




