How to Create Files and Directories in Linux
There is no single "new file" command in Linux. Which one to use depends on whether the file should be empty, get some content right away, or be opened in an editor. Directories are simpler: that is always mkdir.
Create an empty file
touch notes.txt
touch a.txt b.txt c.txt
touch report-{1..5}.md # report-1.md to report-5.md
If the file already exists, touch leaves its content alone and only updates the modification time. That makes it safe to run on any path. Updating timestamps is actually its main job:
touch -d '2026-01-01 12:00' build.stamp # set a specific time
touch -c maybe.txt # update only if it exists, never create
Redirection also creates an empty file:
: > empty.txt
Be careful with this one: > truncates an existing file to zero bytes. > empty.txt on its own works in bash, while : > empty.txt works in any shell, including zsh. When you only want the file to exist, touch is the safer choice.
Create a file with content
echo 'Hello' > hello.txt # create or overwrite
echo 'Second line' >> hello.txt # append
printf 'name=%s\nport=%d\n' my-app 8080 > app.conf
printf is more predictable than echo for multiple lines and escape sequences, since echo -e behaves differently between shells.
For a multi-line file, use a heredoc:
cat > my-site.conf <<'EOF'
server {
listen 80;
server_name example.com;
root /var/www/my-site;
}
EOF
Quoting the delimiter (<<'EOF') keeps $variables literal. With an unquoted <<EOF the shell expands them, which is what you want when templating values from the current environment.
You can also type the content directly: run cat > notes.txt, type, then press Ctrl+D on an empty line to finish.
To stop > from overwriting existing files by accident, turn on noclobber. After that, > refuses to touch an existing file and >| overrides it when you mean it:
set -o noclobber
Create files in root-owned locations
sudo echo 'x' > /etc/file fails with "Permission denied". The redirection is done by your own shell before sudo runs. Use tee, which opens the file itself:
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
echo '203.0.113.10 db.internal' | sudo tee -a /etc/hosts > /dev/null
-a appends instead of overwriting. Redirecting to /dev/null hides the copy that tee prints to the terminal.
Create and edit in an editor
nano todo.txt # type, Ctrl+O to save, Ctrl+X to exit
vim todo.txt # i to type, Esc then :wq to save and quit
The file is created when you save. If you end up in Vim without meaning to, see How to use Vim.
Special cases
mktemp # unique temporary file, prints its path
mktemp -d # unique temporary directory
truncate -s 100M test.img # sparse file that takes no real space yet
fallocate -l 1G big.bin # really allocate 1 GiB (ext4, XFS)
install -m 600 /dev/null secret.env # empty file created with mode 600
The install trick creates the file with the final permissions in one step, so there is no moment when a secrets file is readable by others. In scripts, pair mktemp with a cleanup trap:
tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT
Create a directory
mkdir reports
mkdir logs backups cache
mkdir "Monthly Reports" # quote names with spaces
mkdir -v build # print what was created
Plain mkdir fails in two situations: the parent does not exist (No such file or directory), or the directory already exists (File exists). -p fixes both. It creates missing parents and does nothing if the directory is already there, which is why scripts almost always use it:
mkdir -p projects/my-app/src/components
Brace expansion creates whole trees in one command:
mkdir -p my-app/{src,tests,docs}
mkdir -p data/{2025,2026}/{01..12}
To create a directory and move into it, chain the two commands. && runs cd only if mkdir succeeded:
mkdir -p my-app && cd my-app
Set permissions and owner at creation
mkdir -m 700 ~/private
mkdir -m 2775 /srv/shared
-m sets the mode exactly, ignoring the umask. With -p it applies only to the last directory in the path; parents get the default permissions. To set the owner and group as well, use install -d as root:
sudo install -d -m 750 -o deploy -g www-data /srv/my-app/releases
Check the result with ls -ld /srv/my-app/releases. For more on modes like 2775, see chmod in Linux.
Permission denied
Creating a file or directory needs write and execute permission on the parent directory. In your home directory that is never a problem. In system paths like /etc, /opt or /srv you need sudo, or create the directory once as root and chown it to the user that will work in it.
Quick reference
touch file.txt # empty file, or update timestamp
echo 'text' > file.txt # create or overwrite with content
echo 'more' >> file.txt # append
cat > file.txt <<'EOF' # multi-line content, end with EOF
echo 'x' | sudo tee /etc/file # write a root-owned file
nano file.txt # create in an editor
install -m 600 /dev/null secret.env # empty file with strict mode
mkdir dir # one directory
mkdir -p a/b/c # nested, no error if it exists
mkdir -p app/{src,tests,docs} # several at once
mkdir -m 700 private # with permissions
